javax.xml.bind.UnmarshalException:意外元素。预期元素是(无)

Posted

技术标签:

【中文标题】javax.xml.bind.UnmarshalException:意外元素。预期元素是(无)【英文标题】:javax.xml.bind.UnmarshalException: unexpected element. Expected elements are (none) 【发布时间】:2014-01-02 09:59:27 【问题描述】:

我在解组字符串时收到此错误。我已经使用 JAXB 创建了 Java 文件。

JAXBContext jaxbContext = JAXBContext.newInstance(DocumentType.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
// Input string posted below
DocumentType dType = (DocumentType) unmarshaller.unmarshal(new StringReader("input string"));

堆栈跟踪:

Exception in thread "main" javax.xml.bind.UnmarshalException: unexpected element (uri:"http://ocrsdk.com/schema/recognizedBusinessCard-1.0.xsd", local:"document"). Expected elements are (none)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:647)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:243)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:238)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:105)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1048)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:483)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:465)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:135)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:506)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:376)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:602)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3065)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:881)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:607)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:116)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:489)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:835)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:764)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:123)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1210)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:203)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:175)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:214)
    at JaxbTest.main(JaxbTest.java:19)

XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://ocrsdk.com/schema/recognizedBusinessCard-1.0.xsd"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://ocrsdk.com/schema/recognizedBusinessCard-1.0.xsd"
    elementFormDefault="qualified">

    <xs:element name="document" type="tns:documentType"></xs:element>

    <xs:complexType name="documentType">
        <xs:sequence>
            <xs:element name="businessCard" type="tns:businessCardType" minOccurs="0" maxOccurs="1"></xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="businessCardType">
        <xs:sequence>
            <xs:element name="field" type="tns:fieldType" minOccurs="0" maxOccurs="unbounded"></xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="fieldType">
        <xs:sequence>
            <xs:element name="value" type="xs:string" minOccurs="1" maxOccurs="1">
            </xs:element>
            <xs:element name="characters" type="tns:charactersType" minOccurs="0" maxOccurs="1"></xs:element>
            <xs:element name="fieldComponents" type="tns:fieldComponentsType" minOccurs="0" maxOccurs="1"></xs:element>
        </xs:sequence>
        <xs:attribute name="type" type="tns:typeType"></xs:attribute>
    </xs:complexType>

    <xs:simpleType name="typeType">
        <xs:restriction base="xs:string">
            <xs:enumeration value="Name"></xs:enumeration>
            <xs:enumeration value="Phone"></xs:enumeration>
            <xs:enumeration value="Mobile"></xs:enumeration>
            <xs:enumeration value="Fax"></xs:enumeration>
            <xs:enumeration value="Company"></xs:enumeration>
            <xs:enumeration value="Job"></xs:enumeration>
            <xs:enumeration value="Address"></xs:enumeration>
            <xs:enumeration value="Email"></xs:enumeration>
            <xs:enumeration value="Web"></xs:enumeration>
            <xs:enumeration value="Text"></xs:enumeration>
        </xs:restriction>
    </xs:simpleType>

    <xs:complexType name="charactersType">
        <xs:sequence>
            <xs:element name="char" type="tns:charType" minOccurs="0" maxOccurs="unbounded"></xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="charType">
        <xs:simpleContent>
            <xs:extension base="xs:string">
                <xs:attribute name="suspicious" type="xs:boolean" use="optional"></xs:attribute>
            </xs:extension>
        </xs:simpleContent>
    </xs:complexType>

    <xs:complexType name="fieldComponentsType">
      <xs:sequence>
        <xs:element name="fieldComponent" type="tns:fieldComponentType" minOccurs="0" maxOccurs="unbounded"></xs:element>
      </xs:sequence>
    </xs:complexType>


    <xs:complexType name="fieldComponentType">
      <xs:sequence>
        <xs:element name="value" type="xs:string" minOccurs="1" maxOccurs="1">
        </xs:element>
      </xs:sequence>
      <xs:attribute name="type" type="tns:fieldComponentTypeType"></xs:attribute>
    </xs:complexType>

    <xs:simpleType name="fieldComponentTypeType">
      <xs:restriction base="xs:string">
        <xs:enumeration value="FirstName"></xs:enumeration>
        <xs:enumeration value="MiddleName"></xs:enumeration>
        <xs:enumeration value="LastName"></xs:enumeration>
        <xs:enumeration value="ExtraName"></xs:enumeration>
        <xs:enumeration value="PhonePrefix"></xs:enumeration>
        <xs:enumeration value="PhoneCountryCode"></xs:enumeration>
        <xs:enumeration value="PhoneCode"></xs:enumeration>
        <xs:enumeration value="PhoneBody"></xs:enumeration>
        <xs:enumeration value="PhoneExtension"></xs:enumeration>
        <xs:enumeration value="ZipCode"></xs:enumeration>
        <xs:enumeration value="Country"></xs:enumeration>
        <xs:enumeration value="City"></xs:enumeration>
        <xs:enumeration value="StreetAddress"></xs:enumeration>
        <xs:enumeration value="JobPosition"></xs:enumeration>
        <xs:enumeration value="JobDepartment"></xs:enumeration>
      </xs:restriction>
    </xs:simpleType>

</xs:schema>

输入字符串:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://ocrsdk.com/schema/recognizedBusinessCard-1.0.xsd http://ocrsdk.com/schema/recognizedBusinessCard-1.0.xsd" xmlns="http://ocrsdk.com/schema/recognizedBusinessCard-1.0.xsd">
<businessCard>
<field type="Phone">
  <value>783-37-00</value>
</field>
<field type="Phone">
  <value>783-37-01</value>
</field>
<field type="Fax">
  <value>783-26-63</value>
</field>
<field type="Email">
  <value>john_sm@abbyy.com</value>
</field>
<field type="Web">
  <value>www.abbyy.com</value>
</field>
<field type="Address">
  <value>Otradnaya str., 2b, bld.6, 127273, Moscow, Russia</value>
</field>
<field type="Name">
  <value>John Smith</value>
</field>
<field type="Company">
  <value>ABBYY Headquarters</value>
</field>
<field type="Job">
  <value>Product Analyst</value>
</field>
<field type="Text">
  <value>ABBYY ABBYY Headquarters John Smith Product Analyst ABBYY Headquarters Otradnaya str., 2b, bld.6, 127273, Moscow, Russia Tel: 783-37-00 Fax: 783-26-63 john_sm@abbyy.com www.abbyy.com </value>
</field>
</businessCard>
</document>

【问题讨论】:

【参考方案1】:

在我们的例子中,我们收到 UnmarshalException 是因为下面指定了错误的 Java 包。一旦安装了正确的包,问题就解决了:

@Bean
public Unmarshaller tmsUnmarshaller() 
    final Jaxb2Marshaller jaxb2Marshaller = new Jaxb2Marshaller();
    jaxb2Marshaller
            .setPackagesToScan("java.package.to.generated.java.classes.for.xsd");
    return jaxb2Marshaller;

【讨论】:

【参考方案2】:

此错误的原因之一是使用了 jdk 中的 jaxb 实现。我不确定为什么在非常简单的 xml 解析情况下会出现这样的问题。您可以使用来自公共 maven 存储库的最新版本的 jaxb 库:

http://mvnrepository.com

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.2.12</version>
</dependency>

【讨论】:

【参考方案3】:

当您从 XML Schema 生成 JAXB 模型时,对应于命名复杂类型的全局元素会将元数据捕获为 ObjectFactory 类中的 create 方法上的 @XmlElementDecl 注释。由于您仅在 DocumentType 类上创建 JAXBContext,因此不会处理此元数据。如果您从 XML Schema 生成 JAXB 模型,那么您应该在生成的包名称或 ObjectFactory 类上创建 JAXBContext,以确保处理所有必要的元数据。

示例解决方案:

JAXBContext jaxbContext = JAXBContext.newInstance(my.generatedschema.dir.ObjectFactory.class);
DocumentType documentType = ((JAXBElement<DocumentType>) jaxbContext.createUnmarshaller().unmarshal(inputStream)).getValue();

【讨论】:

工作正常。 unmarshaller.unmarshal() 将返回 JAXBElement 而不是 DocumentType。调用 getValue() 获取被包装的对象。 在我的例子中,调用导入的根元素需要unmarshaller = context.createUnmarshaller(); final Object object = unmarshaller.unmarshal(new File("path/to/data.xml")); final DocumentType cd = (DocumentType)object; 第二步如下:DocumentType doc = ((JAXBElement&lt;DocumentType&gt;) jaxbContext.createUnmarshaller().unmarshal( inputStream)).getValue(); 我得到了和以前一样的错误。但是我可以使用这里建议的匿名根对象方法:***.com/a/15117152/1717259【参考方案4】:

或者,如果您想坚持使用DocumentType 类。 然后,您可以在 DocumentType 类的顶部添加以下注释。

    @XmlRootElement(name="document")

注意:String值"document"指的是xml消息的根标签的名称。

【讨论】:

谢谢,伙计。在为这种情况寻找解决方案大约几个小时后,@XmlRootElement 解决了这个问题。我想知道为什么这种行为应该是这样的。在解组过程中强制这个注释真的有意义吗? @Miere 现在我想起来了。在 Web 服务的世界中,RPC 样式自动提供了一个包装节点,而文档样式的 Web 服务需要显式声明。所以,这一直是一个讨论的领域。 我在 jdk1.6.0_45 中使用 xjc 从 XSD 生成 POJO。 xjc 生成的根 POJO 缺少 @XmlRootElement(name="RootName")。手动添加这一行,解组成功。 它始终是定义其关联的 xml 标记名称的所有者类(例如,使用 @XmlElement(name='...'))。因此,一个类没有定义自己的 xml 标记名称。但是由于根元素没有父节点,这给根元素带来了问题。 存在几种解决方案: XJC 假设您将使用它的ObjectFactory。它使用ObjectFactory 中的@XmlElementDecl 注释定义根节点的名称。但是如果你不想使用ObjectFactory,那么上面的注解(即@XmlRootElement)可能是最简单的解决方案。 我也需要添加@XmlAccessorType(XmlAccessType.FIELD)

以上是关于javax.xml.bind.UnmarshalException:意外元素。预期元素是(无)的主要内容,如果未能解决你的问题,请参考以下文章