java - "generic"现实世界文档的 JAXB 解码

标签 java jaxb unmarshalling

我们有一大套该风格的配置文档

<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 的非常好的输入 - 但是仅仅为了好玩而添加 >7MB 的库不是一个选择。

还有其他想法吗?

最佳答案

您可以使用 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 类:

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)

关于java - "generic"现实世界文档的 JAXB 解码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12402215/

相关文章:

java - 将 XML 转换为 POJO 时出现 ClassCastException

java - io.netty.handler.ssl.OpenSsl 使用 tomcat 类而不是自身

java - 我缺少什么来获得 Java 中的 PHP ScriptEngine

java - Swing GTK L&F 标题栏上的额外按钮

java - JAXB 和列出可通过键访问的属性

java - JaxB 解码自定义 xml

java - Vaadin 应用程序 : handle application closing event

jaxb - wsimport 不生成与 SOAP 头相关的代码

java - 如何在 JAXB 中解码 xml 时处理特殊字符

java - 如何控制 JAXB 内存模式生成顺序/顺序?