JAXBContext.newInstance variations样品a.xml使用JAXB 解析代码

2022-09-02 04:16:45

我正在类 JAXBContext 中试验各种形式的 newInstance 方法(我使用的是 Oracle JDK 1.7 附带的默认 Sun JAXB 实现)。

我不清楚什么时候可以将具体类与ObjectFactory类传递给newInstance方法。我应该注意,我使用JAXB纯粹是为了解析XML文件,即仅在XML->Java方向上。

以下是绝对最少的代码,可以证明我的观点:

xsd 文件

<?xml version="1.0" encoding="UTF-8"?>
<schema elementFormDefault="qualified"
    xmlns          ="http://www.w3.org/2001/XMLSchema"
    xmlns:a        ="http://www.example.org/A"
    targetNamespace="http://www.example.org/A">
    <element name="root" type="a:RootType"></element>

    <complexType name="RootType">
       <sequence>
           <element name="value" type="string"></element>
       </sequence>
    </complexType>
</schema>

给定上述 XSD,以下 JAXBInstance.newInstance 调用成功地创建了一个可以解析示例 a.xml 文件的上下文:

  • jc = JAXBContext.newInstance(“example.a”);
  • jc = JAXBContext.newInstance(example.a.ObjectFactory.class);
  • jc = JAXBContext.newInstance(example.a.RootType.class, example.a.ObjectFactory.class);

但是,单独传递示例.a.RootType.class在运行时使用javax.xml绑定.UnmarshalException时失败:

jc = JAXBContext.newInstance(example.a.RootType.class); // this fails at runtime.

任何人都可以透露一些光明吗?我在这些JAXBContext::newInstance变体上进行实验的原因是,我偶然发现了这个问题,其中接受的答案包括“基于单个类而不是对象工厂构建JAXB上下文”的选项。示例 a.xml和我使用的 JAXB Java 代码在本文末尾。

样品a.xml使用

<?xml version="1.0" encoding="UTF-8"?>
<a:root xmlns:a="http://www.example.org/A"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.example.org/A A.xsd">
    <a:value>foo</a:value>
</a:root>

JAXB 解析代码

public static void main (String args[]) throws JAXBException, FileNotFoundException {
    JAXBContext jc = null;
    message("using package context (press any key:)");
    jc = JAXBContext.newInstance("example.a");
    work(jc); // SUCCEEDS

    message("using Object factory (press any key):");
    jc = JAXBContext.newInstance(example.a.ObjectFactory.class);
    work(jc); // SUCCEEDS

    message("using class enumeration (press any key):");
    try {
        jc = JAXBContext.newInstance(example.a.RootType.class);
        work(jc);  // FAILS
    } catch (javax.xml.bind.UnmarshalException e) {
        e.printStackTrace();
    }

    message("using class enumeration and Object factory too (press any key):");
    jc = JAXBContext.newInstance(example.a.RootType.class, example.a.ObjectFactory.class);
    work(jc); // SUCCEEDS

}

private static void work(JAXBContext jc) throws JAXBException, FileNotFoundException {
    Unmarshaller u = jc.createUnmarshaller();
    RootType root = ((JAXBElement<RootType>)u.unmarshal( new FileInputStream( "a.xml" ))).getValue();
    System.out.println( root.getValue() );
}

答案 1

从 XML 模式生成的 JAXB 模型

在从 XML 架构生成的模型创建模型时,我总是建议对生成的类的包名称执行此操作。JAXBContext

JAXBContext jc = JAXBContext.newInstance("example.a");

使用采用参数的方法甚至更好。当您从 Java SE 迁移到 Java EE 环境时,这将为您省去悲伤。newInstanceClassLoader

JAXBContext jc = JAXBContext.newInstance("example.a", example.a.ObjectFactory.class.getClassLoader());

在包名称上创建 时,JAXB impl 假定您从 XML 模式生成模型并拉入该类,因为它始终生成带有此名称注释的类。JAXBContextObjectFactory@XmlRegistry

从 Java 模型开始

这是我建议人们使用上课的方法的时候。当从 JAXB 类引导 a 时,名为 的类没有什么特别之处。的角色可以由任何带有注释的类扮演,因此不会自动查找。这就是为什么您的用例在您明确引用时有效,而在未引用时失败的原因。newInstanceJAXBContextObjectFactoryObjectFactory@XmlRegistryObjectFactory


答案 2

推荐