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



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

<text id="name">Bu ilk rule</text>
<text id="bundleName">Rule.behavior</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>

解决方法是什么?

编辑:

在Matthias的回答之后,我能得到的最接近所需格式的是:

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

第2版:

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"的文本

第3版:

我在自定义转换器上尝试过类似的东西,但没有成功:

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

第4版

我终于得到了

以下是我的做法:

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

好吧,您显示的代码无法生成此XML。我想在实际代码的某个地方,有一些继承(扩展Test类的类表达式)产生了这个结果。似乎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>

我通过更改前面提到的转换器MAtthia来完成;

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

最新更新