3

我正在使用 org.simpleframework.xml (http://simple.sourceforge.net/) 将 Java 对象序列化为 XML。

我想添加的是基于 Java 对象中的注释在生成的 XML 中添加注释区域。

因此,例如,我想编写一些 Java 对象,例如:

@Root(name = "myclass")
public class MyClass {
  @Element(required=true)
  @Version(revision=1.1)
  @Comment(text=This Element is new since, version 1.1, it is a MD5 encrypted value)
  private String activateHash;
}

生成的 xml 如下所示:

<myclass version="1.1">
  <!-- This Element is new since, version 1.1, it is a MD5 encrypted value -->
  <activateHash>129831923131s3jjs3s3jjk93jk1</activateHash>
</myclass>

他们的文档中有一个关于如何编写访问者的示例,该访问者将在 xml 中编写评论:http: //simple.sourceforge.net/download/stream/doc/tutorial/tutorial.php#intercept

但是:我如何才能将访客附加到策略?

此外,simpleframework 的访问者概念不允许访问原始解析类。在访问者中,只有一种方法可以覆盖:

public void write(Type type, NodeMap<OutputNode> node) { ... }

=> OutputNode 没有让我有机会阅读我正在解析的元素的注释。那么应该如何访问属性的注释。

谢谢!

塞巴斯蒂安

4

1 回答 1

2

截至 2012 年 11 月 5 日的更新:

org.simpleframework.xml 的作者回答:这行得通

https://simple.svn.sourceforge.net/svnroot/simple/trunk/download/stream/src/test/java/org/simpleframework/xml/strategy/CommentTest.java

package org.simpleframework.xml.strategy;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import org.simpleframework.xml.Default;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.ValidationTestCase;
import org.simpleframework.xml.core.Persister;
import org.simpleframework.xml.stream.InputNode;
import org.simpleframework.xml.stream.NodeMap;
import org.simpleframework.xml.stream.OutputNode;

public class CommentTest extends ValidationTestCase {

   @Retention(RetentionPolicy.RUNTIME)
   private static @interface Comment {
      public String value();
   }

   @Root
   @Default
   private static class CommentExample {
      @Comment("This represents the name value")
      private String name;
      @Comment("This is a value to be used")
      private String value;
      @Comment("Yet another comment")
      private Double price;
   }

   private static class CommentVisitor implements Visitor {
      public void read(Type type, NodeMap<InputNode> node) throws Exception {}
      public void write(Type type, NodeMap<OutputNode> node) throws Exception {
         if(!node.getNode().isRoot()) {
            Comment comment = type.getAnnotation(Comment.class);
            if(comment != null) {
               node.getNode().setComment(comment.value());
            }
         }
      }
   }

   public void testComment() throws Exception {
      Visitor visitor = new CommentVisitor();
      Strategy strategy = new VisitorStrategy(visitor);
      Persister persister = new Persister(strategy);
      CommentExample example = new CommentExample();

      example.name = "Some Name";
      example.value = "A value to use";
      example.price = 9.99;

      persister.write(example, System.out);
   }

}

更新于 2012-11-01 20:16

这是似乎达到预期效果的解决方法 - 必要的 FieldHelper 在(Get the value of a field, given the hierarchy path)中描述

    /**
     * write according to this visitor
     */
    public void write(Type type, NodeMap<OutputNode> node) {
        OutputNode element = node.getNode();
        Class ctype = type.getType();

        String comment = ctype.getName();
        if (!element.isRoot()) {
            FieldHelper fh = new FieldHelper();
            element.setComment(comment);
            try {
                if (type.getClass().getSimpleName().startsWith("Override")) {
                    type = (Type) fh.getFieldValue(type, "type");
                }
                if (type.getClass().getSimpleName().startsWith("Field")) {
                    Field field = (Field) fh.getFieldValue(type, "field");
                    System.out.println(field.getName());
                    Comment commentAnnotation = field.getAnnotation(Comment.class);
                    if (commentAnnotation != null) {
                        element.setComment(commentAnnotation.value());
                    }
                }
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

这是我在这方面取得的进展。不幸的是,它没有按预期工作。我已经给 Simpleframwork for XML 的作者写了一封电子邮件。

  /**
  * write according to this visitor
  */
    public void write(Type type, NodeMap<OutputNode> node) {
        OutputNode element = node.getNode();
        Class ctype = type.getType();

        String comment = ctype.getName();
        if (!element.isRoot()) {
            Comment commentAnnotation = type.getAnnotation(Comment.class);
            if (commentAnnotation!=null)
                element.setComment(commentAnnotation.value());
            else
                element.setComment(comment);
        }
    }

    @Override
    public void read(Type type, NodeMap<InputNode> nodeMap) throws Exception {

    }

}

我这样声明了 Comment 注释:

package com.bitplan.storage.simplexml;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Comment {
String value();
}

然后可以像这样使用:

@Comment("this is the unique identifier")
private long id;

可以像这样添加访客:

/**
 * get Serializer
 * 
 * @return
 */
public Serializer getSerializer() {
    Serializer serializer = null;
    Strategy strategy=null;
    VisitorStrategy vstrategy=null;
    if ((idname != null) && (refname != null)) {
        strategy = new CycleStrategy(idname, refname);
    }
    CommentVisitor cv=new CommentVisitor();
    if (strategy==null) {
        vstrategy=new VisitorStrategy(cv);
    } else {
        vstrategy=new VisitorStrategy(cv,strategy);
    }       
    serializer = new Persister(vstrategy);
    return serializer;
}
于 2012-11-02T16:54:36.800 回答