如何扩展 org.simpleframework.xml 带有注释,该注释会将注释写入生成的 XML



我正在使用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

但是:如何将访客附加到策略中?

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

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

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

谢谢!

塞巴斯蒂安

更新截至 2012-11-05:

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 在(给定分层路径的情况下获取字段的值)中描述

    /**
     * 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 {
    }
}

我像这样声明注释注释:

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;
}

最新更新