开发者社区> 问答> 正文

手动编写的XSD和生成的Java类使用JAXB导致UnmarshallException

我刚接触JAVA和阅读XML。我习惯于使用C#.net中的XSD解析XML。对这个主题的研究让我开始使用JAXB,但我无法使其正常工作。我使用示例XML编写了单元测试,但这会产生一个晦涩的异常(在我看来)。

因此,我们有一个如下所示的XSD:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Jabberpoint">
    <xs:complexType>
      <xs:sequence>
        <xs:element minOccurs="1" maxOccurs="1" name="Slideshows" type="Slideshows" />
        <xs:element minOccurs="1" maxOccurs="1" name="Slides" type="Slides" />
        <xs:element minOccurs="0" maxOccurs="1" name="Components" type="Components" />
      </xs:sequence>
    </xs:complexType>
    <xs:keyref name="slideKeyRef" refer="slideKey">
      <xs:selector xpath="Slideshows/Slideshow/Slide" />
      <xs:field xpath="@id" />
    </xs:keyref>
    <xs:key name="slideKey">
      <xs:selector xpath="Slides/Slide"/>
      <xs:field xpath="Id"/>
    </xs:key>
  </xs:element>

  <xs:complexType name="PresentationParserDTO" />

  <xs:complexType name="Slideshows">
    <xs:sequence maxOccurs="unbounded">
      <xs:element minOccurs="1" maxOccurs="unbounded" name="Slideshow" type="SlideshowParserDTO" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="Slides">
    <xs:sequence maxOccurs="unbounded">
      <xs:element minOccurs="1" maxOccurs="unbounded" name="Slide" type="SlideParserDTO" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="Components">
    <xs:sequence maxOccurs="unbounded">
      <xs:element minOccurs="0" maxOccurs="unbounded" name="Component" type="SlideComponentDTO" />
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="SlideshowParserDTO">
    <xs:complexContent mixed="false">
      <xs:extension base="PresentationParserDTO">
        <xs:sequence>
          <xs:element name="Slide" minOccurs="1" maxOccurs="unbounded">
            <xs:complexType>
              <xs:attribute name="id" type="xs:string"/>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="SlideParserDTO">
    <xs:complexContent mixed="false">
      <xs:extension base="PresentationParserDTO">
        <xs:sequence>
          <xs:element minOccurs="1" maxOccurs="1" name="Id" type="xs:string"/>
          <xs:element minOccurs="0" maxOccurs="unbounded" name="Component">
            <xs:complexType>
              <xs:attribute name="id" type="xs:string"/>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="SlideComponentDTO">
    <xs:complexContent mixed="false">
      <xs:extension base="PresentationParserDTO">
        <xs:sequence>
          <xs:element minOccurs="1" maxOccurs="1" name="Id" type="xs:string"/>
          <xs:element minOccurs="0" maxOccurs="1" name="Item" type="SlideItemParserDTO" />
          <xs:element minOccurs="0" maxOccurs="1" name="Children">
            <xs:complexType>
              <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="unbounded" name="Component">
                  <xs:complexType>
                    <xs:attribute name="id" type="xs:string"/>
                  </xs:complexType>
                </xs:element>
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="SlideItemParserDTO" abstract="true">
    <xs:complexContent mixed="false">
      <xs:extension base="PresentationParserDTO" />
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="LexicalItemParserDTO" abstract="true">
    <xs:complexContent mixed="false">
      <xs:extension base="SlideItemParserDTO">
        <xs:sequence>
          <xs:element minOccurs="1" maxOccurs="1" name="Text" type="xs:string" />
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="Text">
    <xs:complexContent mixed="false">
      <xs:extension base="LexicalItemParserDTO" />
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="Title">
    <xs:complexContent mixed="false">
      <xs:extension base="LexicalItemParserDTO" />
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="Media">
    <xs:complexContent mixed="false">
      <xs:extension base="SlideItemParserDTO">
        <xs:sequence>
          <xs:element minOccurs="1" maxOccurs="1" name="Source" type="xs:string" />
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="Table">
    <xs:complexContent mixed="false">
      <xs:extension base="SlideItemParserDTO">
        <xs:sequence>
          <xs:element minOccurs="1" maxOccurs="unbounded" name="tr" type="TableRowParserDTO" />
        </xs:sequence>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

  <xs:complexType name="TableRowParserDTO">
    <xs:sequence>
      <xs:element minOccurs="1" maxOccurs="unbounded" name="td" type="xs:string" />
    </xs:sequence>
  </xs:complexType>
</xs:schema>

从中我生成了这样的类:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "slideshows",
    "slides",
    "components"
})
@XmlRootElement(name = "Jabberpoint")
public class Jabberpoint {

    @XmlElement(name = "Slideshows", required = true)
    protected Slideshows slideshows;
    @XmlElement(name = "Slides", required = true)
    protected Slides slides;
    @XmlElement(name = "Components")
    protected Components components;

    /**
     * Gets the value of the slideshows property.
     * 
     * @return
     *     possible object is
     *     {@link Slideshows }
     *     
     */
    public Slideshows getSlideshows() {
        return slideshows;
    }

    /**
     * Sets the value of the slideshows property.
     * 
     * @param value
     *     allowed object is
     *     {@link Slideshows }
     *     
     */
    public void setSlideshows(Slideshows value) {
        this.slideshows = value;
    }

    /**
     * Gets the value of the slides property.
     * 
     * @return
     *     possible object is
     *     {@link Slides }
     *     
     */
    public Slides getSlides() {
        return slides;
    }

    /**
     * Sets the value of the slides property.
     * 
     * @param value
     *     allowed object is
     *     {@link Slides }
     *     
     */
    public void setSlides(Slides value) {
        this.slides = value;
    }

    /**
     * Gets the value of the components property.
     * 
     * @return
     *     possible object is
     *     {@link Components }
     *     
     */
    public Components getComponents() {
        return components;
    }

    /**
     * Sets the value of the components property.
     * 
     * @param value
     *     allowed object is
     *     {@link Components }
     *     
     */
    public void setComponents(Components value) {
        this.components = value;
    }
}

解析器如下所示:

public class XMLPresentationParser {
    public Jabberpoint Parse(InputStream inputstream) throws MalformedURLException, SAXException, JAXBException {
        var jc = JAXBContext.newInstance(PresentationParserDTO.class);
        var unmarshaller = jc.createUnmarshaller();


        var schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
        var file = new File("./src/Jabberpoint/Schema/slideshow.xsd");
        var schema = schemaFactory.newSchema(file);
        unmarshaller.setSchema(schema);

        var element = (JAXBElement<Jabberpoint>) unmarshaller.unmarshal(inputstream);
        return element.getValue();
    }
}

然后,我创建了一个单元测试,以检查是否可以读取和解析一个简单的XML文件:

public class AllTests {

    @Test
    public void Test() throws FileNotFoundException, MalformedURLException, SAXException, JAXBException {
        // Assert
        var target = new XMLPresentationParser();
        var inputstream = new FileInputStream(getClass().getResource("slideshow.xml").getPath());
        // Act
        var result = target.Parse(inputstream);

        // Assert
        assertNotNull(result);
        // TODO: real assert
    }
}

使用这个简单的示例XML文件:

<?xml version="1.0" encoding="utf-8"?>
<Jabberpoint>
  <Slideshows>
    <Slideshow>
      <Slide id="d62f4edd-10d3-4f2d-95b7-ca5c75525688" />
      <Slide id="40a63503-ed5c-4e8a-b170-dec630f28798" />
    </Slideshow>

    <Slideshow>
      <Slide id="2a4aef8c-22b4-4439-bbbe-ef27a90d64c1" />
      <Slide id="40a63503-ed5c-4e8a-b170-dec630f28798" />
    </Slideshow>
  </Slideshows>
  <Slides>
    <Slide>
      <Id>d62f4edd-10d3-4f2d-95b7-ca5c75525688</Id>
      <Component id="822a7698-2a87-4c16-88fe-7b416fd64a20" />
      <Component id="e0049245-7346-4952-b8ce-05e25b6f3331"/>
    </Slide>

    <Slide>
      <Id>2a4aef8c-22b4-4439-bbbe-ef27a90d64c1</Id>
      <Component id="a264f972-e24e-4674-85c3-e08ff6f29d76"/>
      <Component id="e0049245-7346-4952-b8ce-05e25b6f3331"/>
    </Slide>

    <Slide>
      <Id>40a63503-ed5c-4e8a-b170-dec630f28798</Id>
      <Component id="c70121d9-63a7-49d4-9edd-afd5d314a3f7" />
    </Slide>
  </Slides>

  <Components>
    <Component>
      <Id>822a7698-2a87-4c16-88fe-7b416fd64a20</Id>
      <Item xsi:type="Title">
        <Text>This is Slideshow number 1</Text>
      </Item>
    </Component>

    <Component>
      <Id>a264f972-e24e-4674-85c3-e08ff6f29d76</Id>
      <Item xsi:type="Title">
        <Text>This is Slideshow number 2</Text>
      </Item>
    </Component>

    <Component>
      <Id>c70121d9-63a7-49d4-9edd-afd5d314a3f7</Id>
      <Item xsi:type="Title">
        <Text>This Component contains some images and a table</Text>
      </Item>
      <Children>
        <Component id="18da47d6-aebe-4525-af2e-20418bb0b1d8" />
        <Component id="5ba057c8-857e-4d3e-9466-9f27c4c26676" />
        <Component id="e0049245-7346-4952-b8ce-05e25b6f3331"/>
      </Children>
    </Component>

    <Component>
      <Id>18da47d6-aebe-4525-af2e-20418bb0b1d8</Id>
      <Item xsi:type="Media">
        <Source>img1.jpg</Source>
      </Item>
    </Component>

    <Component>
      <Id>5ba057c8-857e-4d3e-9466-9f27c4c26676</Id>
      <Item xsi:type="Media">
        <Source>img1.jpg</Source>
      </Item>
    </Component>

    <Component>
      <Id>e0049245-7346-4952-b8ce-05e25b6f3331</Id>
      <Item xsi:type="Table">
        <tr>
          <td>Apples</td>
          <td>Bananas</td>
        </tr>
      </Item>
    </Component>
  </Components>
</Jabberpoint>

运行此测试会产生以下错误。为什么会出现此错误?还有使用XSD读取XML的更好方法吗?我主要使用JAXB,因此不必自己编写解析器。

AllTests
Jabberpoint.Infrastructure.Tests.AllTests
Test(Jabberpoint.Infrastructure.Tests.AllTests)
javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"Jabberpoint"). Expected elements are (none)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:741)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:262)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:257)
    at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:124)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1149)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:574)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:556)
    at com.sun.xml.bind.v2.runtime.unmarshaller.ValidatingUnmarshaller.startElement(ValidatingUnmarshaller.java:102)
    at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:168)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:510)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:374)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:613)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3078)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:836)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:605)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
    at java.xml/com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:541)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:888)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:824)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
    at java.xml/com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1216)
    at java.xml/com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:635)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:258)
    at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:229)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:170)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:209)
    at Jabberpoint.Infrastructure.XMLPresentationParser.Parse(XMLPresentationParser.java:31)
    at Jabberpoint.Infrastructure.Tests.AllTests.Test(AllTests.java:28)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:40)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
    at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
    at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133)
    at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
    at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
    at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
    at org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:80)
    at org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:71)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:229)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$6(DefaultLauncher.java:197)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:191)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:137)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)

问题来源:Stack Overflow

展开
收起
montos 2020-03-22 08:48:31 936 0
1 条回答
写回答
取消 提交回答
  • 您正在为错误的顶级类创建JAXContext:

    var jc = JAXBContext.newInstance(PresentationParserDTO.class); 应该:

    var jc = JAXBContext.newInstance(Jabberpoint.class); 同样,解组步骤的演员表应该是Jabberpoint,而不是JAXBElement<Jabberpoint>

    回答来源:Stack Overflow

    2020-03-22 08:49:20
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
JAVA开发手册1.5.0 立即下载