0

我怀疑是否可以使用 XStream 忽略转换表单 Object to XML 上的 xml 根元素,或者是否有任何方法可以将根元素替换为其他元素,我的意思是:

我有一个函数可以将自定义运行时创建的对象解析为 XML,例如:

public static String entityToXML(GenericResponseObject entity) {
    XStream xstream = new XStream(new StaxDriver());

    xstream.autodetectAnnotations(true);
    xstream.registerConverter(new GenericResponseAttributeConverter());
    String xml = xstream.toXML(entity);

    return xml;
}

为此,我弄得一团糟:

我有 GenericResponseObject 和 GenericResponseAttribute 类,想法是在运行时拥有一个具有尽可能多的自定义属性的对象:

@XStreamAlias("objectResult")
public class GenericResponseObject {

    @XStreamAlias("attributes")
    @XStreamImplicit
    private ArrayList<GenericResponseAttribute> attributes;

    public GenericResponseObject() {
        this.attributes = new ArrayList();
    }

    public void addAttribute(String name, Object value) {
        this.attributes.add(new GenericResponseAttribute(name, value));
    }
}

以及 GenericResponseAttribute 类:

@XStreamAlias("attribute")
public class GenericResponseAttribute {

    private String name;
    private Object value;

    public GenericResponseAttribute(String name, Object value) {
        this.name = name;
        this.value = value;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Object getValue() {
        return this.value;
    }

    public void setValue(Object value) {
        this.value = value;
    }
}

正如您所读到的,每个类都有其用于别名和隐式列表的 XStream 注释,因此,让我向您展示我为 GenericResponseAttribute 类制作的自定义转换器:

public class GenericResponseAttributeConverter implements Converter {

    @Override
    public boolean canConvert(Class type) {
        return type.equals(GenericResponseAttribute.class);
    }

    @Override
    public void marshal(Object o, HierarchicalStreamWriter writer, MarshallingContext mc) {
        GenericResponseAttribute value = (GenericResponseAttribute)o;
        writer.startNode(value.getName());
        mc.convertAnother(value.getValue());
        writer.endNode();
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext uc) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

因此,如果我在运行时构建一个 GenericResponseObject,并使用我的静态方法将其解析为 XML,则 K 会得到如下内容:

response = new GenericResponseObject();
response.addAttribute("user", "alex");
response.addAttribute("otherAtt", "TEST");
System.out.println(XMLUtil.entityToXML(response));

println() 函数的结果是:

<objectResult>
    <attribute>
        <user>hugo</user>
    </attribute>
    <attribute>
        <otherAtt>TEST</otherAtt>
    </attribute>
</objectResult>

这几乎是我想要的,但我真的需要省略 GenericResponseAttribute 类上的根元素,重要的是要说对于我上面显示的根节点,总是只存在一个节点,属性名称与属性值的内容。因此,如果我删除当前元素,它将始终是一个根元素,例如,我需要的 previos XML 的结果是:

<objectResult>
    <user>hugo</user>
    <otherAtt>TEST</otherAtt>
</objectResult>

我的需求非常基本,但我不知道如何正确处理,我已经搜索过,似乎 HierarchicalStreamWriter 类中没有像 deletRootNode() 或 replaceRootNode() 这样的方法,也没有 @XStreamNoRoot 或 @XStreamMakeRoot 注释我可以在 GenericResponseAttribute 中使用,所以,这就是我在这里问的原因,如果你知道如何做到这一点,请帮助我。

谢谢。

4

2 回答 2

2

当我在将对象解析为 XML 后最终使用字符串替换时,我的意思是:

public static String entityToXML(Object entity) {
    XStream xstream = new XStream(new StaxDriver());

    xstream.autodetectAnnotations(true);
    xstream.registerConverter(new GenericResponseAttributeConverter());
    String xml = xstream.toXML(entity);

    xml = xml.replace("<attribute>", "");
    xml = xml.replace("</attribute>", "");

    return xml;
}

但是,这不是一个很酷的解决方案,如果您有另一个解决方案,请告诉我。

谢谢。

于 2012-11-12T17:22:45.153 回答
0

我提出的解决方案是基于对类结构的修改,因为我找不到动态改变字段的方法,我认为这不是一个好习惯。实际上,xml 结构必须始终相同,但您可以跳过一些在 POJO 中将它们设置为 null 的字段

在我的解决方案中,我更改了问题的两个类别,最后有一个示例说明如何将 xml 映射到相应的对象并编辑添加额外属性的对象,然后将其映射到具有新属性的 xml 字符串

这是我的解决方案:

    @XStreamAlias("attribute")
    class GenericResponseAttribute {

        @XStreamAlias("user")
        private String user;

        @XStreamAlias("otherAtt")
        private String otherAtt;

        public GenericResponseAttribute(String user, String otherAttr) {
            super();
            this.user = user;
            this.otherAtt = otherAttr;
        }



    }

    @XStreamAlias("objectResult")
    class GenericResponseObject {

        @XStreamAlias("attributes")
        @XStreamImplicit
        private ArrayList<GenericResponseAttribute> attributes;

        public GenericResponseObject() {
            this.attributes = new ArrayList<>();
        }

        public void addAttribute(String name, String otherAttr) {
            this.attributes.add(new GenericResponseAttribute(name, otherAttr));
        }
    }

    String xml=""+
            "<objectResult>"+
            "   <attribute>"+
            "       <user>hugo</user>"+
            "   </attribute>"+
            "   <attribute>"+
            "       <otherAtt>TEST</otherAtt>"+
            "   </attribute>"+
            "</objectResult>";

    XStream stream=new XStream();
    XStream.setupDefaultSecurity(stream);
    stream.autodetectAnnotations(true);
    stream.addPermission(AnyTypePermission.ANY);
    stream.autodetectAnnotations(true);
    stream.allowTypes(new Class[] {GenericResponseObject.class});
    stream.addImplicitCollection(GenericResponseObject.class, "attributes", GenericResponseAttribute.class);
    stream.alias("objectResult", GenericResponseObject.class);
    GenericResponseObject obj = (GenericResponseObject) stream.fromXML(xml);
    obj.addAttribute("another", "3");
    String xml2 = stream.toXML(obj);
    System.out.println(xml2);
于 2019-01-22T10:27:49.243 回答