我刚接触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
您正在为错误的顶级类创建JAXContext:
var jc = JAXBContext.newInstance(PresentationParserDTO.class);
应该:
var jc = JAXBContext.newInstance(Jabberpoint.class);
同样,解组步骤的演员表应该是Jabberpoint
,而不是JAXBElement<Jabberpoint>
。
回答来源:Stack Overflow
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。