我们有一大堆风格的配置文档
<foo>
<bar class="com.diedel.Gnarf">
...more content
</bar>
<bar class="de.doedel.Bork">
..more content
</bar>
...
</foo>
通用实现类都是使用Jaxb自己映射的。
在我最终回归到Xstream之前,向社区提出一个问题:是否有一种(非黑客)方式可以在Jaxb中解组。到目前为止我们尝试使用@XMLAdapter进行“嵌套”解组,其中“bar”字段获取Element,获取目标类并调用另一个“unmarshall”循环。这种方法已经a)非常慢并且b)在切换到Java 7时被破坏,其中一些神奇的ThreadLocal在从内部unmarshall返回时破坏了上下文。
我发现MOXy可以使用@XmlDiscriminatorNode支持这个 - 这看起来是一个很好的解决方案,我非常喜欢Blaise的非常好的输入 - 但是为了好玩添加一个&gt; 7MB的lib不是一种选择。
其他想法?
答案 0 :(得分:3)
您可以使用JAXB (JSR-222)和StAX (JSR-173)执行以下操作:
<强>演示强>
StAX XMLStreamReader
可用于解析XML文档。您可以使用它前进到bar
元素,然后您可以阅读class
属性并从ClassLoader
加载适当的Java类。然后,您可以利用带有类参数的unmarshal
方法之一。
package forum12402215;
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
ClassLoader classLoader = Bork.class.getClassLoader();
JAXBContext jc = JAXBContext.newInstance(Bork.class, Gnarf.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StreamSource source = new StreamSource("src/forum12402215/input.xml");
XMLInputFactory xif = XMLInputFactory.newFactory();
XMLStreamReader xsr = xif.createXMLStreamReader(source);
xsr.nextTag(); // Advance to "foo" element
xsr.nextTag(); // Advance to "bar" element
while(xsr.getLocalName().equals("bar")) {
String className = xsr.getAttributeValue("", "class");
Class<?> clazz = classLoader.loadClass(className);
Object object = unmarshaller.unmarshal(xsr, clazz).getValue();
System.out.println(object);
xsr.nextTag();
}
}
}
<强>博克强>
以下是示例Bork
类。
package forum12402215;
public class Bork {
private String b;
public String getB() {
return b;
}
public void setB(String b) {
this.b = b;
}
@Override
public String toString() {
return "Bork(b=" + b + ")";
}
}
<强> Gnarf 强>
以下是Gnarf
类示例:
package forum12402215;
public class Gnarf {
private int a;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
@Override
public String toString() {
return "Gnarf(a=" + a + ")";
}
}
<强> input.xml中强>
以下是我根据您的问题使用的示例文档。我更改了包名。
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar class="forum12402215.Gnarf">
<a>123</a>
</bar>
<bar class="forum12402215.Bork">
<b>Hello World</b>
</bar>
</foo>
<强>输出强>
以下是运行演示代码的输出。
Gnarf(a=123)
Bork(b=Hello World)
答案 1 :(得分:2)
如果结构真的那么简单,我很想用XMLStreamReader
自己解析前两个级别(foo和bar的class属性),然后将读者移到JAXB unmarshaller来解析每个栏,将结果汇总到一个列表中。我不打算尝试直接使用JAXB解析外包层。