XStream和'ToAttributedValueConverter'用于两个相似但不同的XML字段

时间:2013-12-20 00:19:26

标签: java xstream

在我的XML文件中,我有这样的行;

    <text id="name">Bu ilk rule</text>
    <text id="bundleName">Rule.behavior</text>

所以我的Text类是这样的:

@XStreamConverter(value = ToAttributedValueConverter.class, strings = {"value"})
@XStreamAlias("text")
public class Text {

    @XStreamAsAttribute
    String id = "unset";
    String value = "0";
}

它有效。但今天我用XML得到了这个:

        <text id="targetAttribute">game.devices.touches.touch1.y</text>
        <text id="RHS">
          <expression>
            <string>acos(x)</string>
          </expression>
        </text>

它不起作用。如果我删除@XStreamConverter,我会得到这样的输出:

        <text id="targetAttribute"/>
        <text id="RHS">
          <expression>
            <string>acos(x)</string>
          </expression>
        </text>

这是什么解决方法?

修改

马蒂亚斯回答后,我能得到最接近的格式是:

        <text id="RHS">
          <expression>
            <string>acos(x)</string>
          </expression>
        </text>

但是这种方法失败了,它开始没有显示“值”字段:

        <text id="name"/>
        <text id="bundleName"/>
        <text id="targetAttribute"/>

使用这个课程:

@XStreamAlias("text")

class Test {

    @XStreamAsAttribute
    String id = "unset";
    String value = "0";
    myString string = new myString();
    Expression expression = new Expression();

}

另外,我这样做的阅读,所以在这样做时必须有效:

String xml1 = readFile("C:\\1.xml");
Actor actorNew = (Actor) xstream.fromXML(xml1);

String xmlNew = xstream.toXML(actorNew);
System.out.println(xmlNew);

EDIT2:

XML中<string>的myString类:

@XStreamConverter(value = ToAttributedValueConverter.class, strings = {"value"})
public class myString {

    @XStreamAlias("string")
    String value = "";

}

这是我正在尝试阅读的XML的缩小视图:

<behaviors>
        <behavior id="id384781" class="ChangeAttributeAction" enabled="true">
          <attributes>
            <text id="name">Change Attribute</text>
            <text id="bundleName">ChangeAttribute.behavior</text>
            <text id="targetAttribute">game.devices.touches.touch1.y</text>
            <text id="RHS">
              <expression>
                <string>acos(x)</string>
              </expression>
            </text>
          </attributes>
        </behavior>
</behaviors>

所有工作都在工作,直到id =“RHS”的文本

EDIT3:

我在自定义转换器上尝试了类似的功能,但没有工作:

@Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
    Test test = new Test();
    test.expression = new Expression();
    test.expression.string = new myString();
    test.value = reader.getValue();
    test.id = reader.getAttribute("id");
    reader.moveDown();
    reader.moveDown();
    test.expression.string.value = reader.getValue();
    return test;
}

Edit4

WOOOOOOOOOOOOOOOOOOOOOO我最后得到了它!

我是这样做的:

class ValueConverter implements Converter {

    @Override
    public boolean canConvert(Class type) {
        return Test.class.isAssignableFrom(type);
    }

    @Override
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        Test src = (Test) source;
        writer.addAttribute("id", src.id);
        writer.setValue(src.value);

        if (src.expression.string.value.length() > 0) {
            writer.startNode("expression");
            writer.startNode("string");
            writer.setValue(src.expression.string.value);
            writer.endNode();
        }

    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        Test test = new Test();
        test.id = reader.getAttribute("id");
        test.value = reader.getValue();
        if (reader.hasMoreChildren()) {
            reader.moveDown();
            reader.moveDown();
            test.expression.string.value = reader.getValue();

        }
        return test;
    }

}

2 个答案:

答案 0 :(得分:1)

嗯,您显示的代码无法生成此XML。我猜你真正的代码中有一些继承(一个扩展你的Test类的类Expression),它产生了这个结果。似乎ToAttributedValueConverter对派生类不起作用,并在那里被忽略。

如果您想要映射到非常特定的XML表示的更复杂的对象结构,则应使用转换器。有疑问,您始终可以创建一个处理编组/解组的自定义转换器。 对于这些转换器,您可以轻松定义应使用哪些类(请参阅canConvert(Class)方法。

我为你做了一个非常相似的代码:

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;

@XStreamAlias("text")
class Test {

  String id = "unset";
  String value = "0";
}

@XStreamAlias("expression")
class Expression extends Test {
  Expression() {
    value = "acos(x)";
  }
}

class ValueConverter implements Converter {

  @Override
  public boolean canConvert(Class type) {
    return Test.class.isAssignableFrom(type);
  }

  @Override
  public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
    Test src = (Test)source;
    writer.addAttribute("id", src.id);
    writer.setValue(src.value);
  }

  @Override
  public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
    Test test = new Test();
    test.value = reader.getValue();
    test.id = reader.getAttribute("id");
    return test;
  }

}

public class Example {
  public static void main(String[] args) {
    XStream xStream = new XStream();
    xStream.autodetectAnnotations(true);
    System.out.println("BEFORE setting a converter:");
    System.out.println(xStream.toXML(new Test()));
    System.out.println(xStream.toXML(new Expression()));
    xStream.registerConverter(new ValueConverter());
    System.out.println("\nAFTER setting a converter:");
    System.out.println(xStream.toXML(new Test()));
    System.out.println(xStream.toXML(new Expression()));
  }
}

运行此命令,您将获得以下输出:

<text>
  <id>unset</id>
  <value>0</value>
</text>
<expression>
  <id>unset</id>
  <value>acos(x)</value>
</expression>

AFTER setting a converter:
<text id="unset">0</text>
<expression id="unset">acos(x)</expression>

答案 1 :(得分:1)

我是通过更改提到的转换器MAtthias来完成的;

class ValueConverter implements Converter {

    @Override
    public boolean canConvert(Class type) {
        return Test.class.isAssignableFrom(type);
    }

    @Override
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        Test src = (Test) source;
        writer.addAttribute("id", src.id);
        writer.setValue(src.value);

        if (src.expression.string.value.length() > 0) {
            writer.startNode("expression");
            writer.startNode("string");
            writer.setValue(src.expression.string.value);
            writer.endNode();
        }

    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        Test test = new Test();
        test.id = reader.getAttribute("id");
        test.value = reader.getValue();
        if (reader.hasMoreChildren()) {
            reader.moveDown();
            reader.moveDown();
            test.expression.string.value = reader.getValue();

        }
        return test;
    }

}