JAXB反序列化异常:意外元素(uri:"", local:"network")求助
JAXB反序列化XML到Network对象时抛出UnmarshalException异常的解决方法
问题描述
使用JAXB将XML文件反序列化为Network对象时,抛出javax.xml.bind.UnmarshalException异常,提示:
unexpected element (uri:"", local:"network"). Expected elements are <{urn:com.myproject.server.ws.dto.cfg}FullSiteDiversity>,<{urn:com.myproject.server.ws.dto.cfg}Network>,<{urn:com.myproject.server.ws.dto.cfg}SupportedFeatures>
POJO代码
@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "Network", namespace = "urn:com.myproject.server.ws.dto.cfg") @XmlType(name = "Network", namespace = "urn:com.myproject.server.ws.dto.cfg") public class Network { @NotNull @Valid private NetworkSupportedFeaturesSection supportedFeatures; @Valid private NetworkFullSiteDiversitySection fullSiteDiversity; public NetworkSupportedFeaturesSection getSupportedFeatures() { return supportedFeatures; } public void setSupportedFeatures(NetworkSupportedFeaturesSection supportedFeatures) { this.supportedFeatures = supportedFeatures; } public NetworkFullSiteDiversitySection getFullSiteDiversity() { return fullSiteDiversity; } public void setFullSiteDiversity(NetworkFullSiteDiversitySection fullSiteDiversity) { this.fullSiteDiversity = fullSiteDiversity; } }
XML内容
<network> <supportedFeatures> <nmsDiversity>ENABLE</nmsDiversity> <fullSiteDiversity>ENABLE</fullSiteDiversity> </supportedFeatures> <fullSiteDiversity> <activeDc>DC2</activeDc> <active1NGw>My_Teleport_5_GW_Main</active1NGw> </fullSiteDiversity> </network>
单元测试代码
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; @Test public void should_throw_exception_with_error_message_when_execute_operation_with_corrupted_parameter2() throws IOException { URL url = getClass().getResource(PATH_TO_FULL_SITE_DIVERSITY_RESOURCES + "/network_node.xml"); Optional<Network> network = convertXMLToObject(url); } private static Optional<Network> convertXMLToObject(URL url) { try { JAXBContext context = JAXBContext.newInstance(Network.class); Unmarshaller un = context.createUnmarshaller(); return Optional.of((Network) un.unmarshal(url)); // 报错位置 } catch (JAXBException e) { LOGGER.error(e.getMessage(), e); } return Optional.empty(); }
完整报错堆栈
2023-05-30 15:11:57.705 ERROR [NetworkWebServiceTest:main] unexpected element (uri:"", local:"network"). Expected elements are <{urn:com.myproject.server.ws.dto.cfg}FullSiteDiversity>,<{urn:com.myproject.server.ws.dto.cfg}Network>,<{urn:com.myproject.server.ws.dto.cfg}SupportedFeatures> javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"network"). Expected elements are <{urn:com.myproject.server.ws.dto.cfg}FullSiteDiversity>,<{urn:com.myproject.server.ws.dto.cfg}Network>,<{urn:com.myproject.server.ws.dto.cfg}SupportedFeatures> at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:712) ~[jaxb-runtime-2.3.5.jar:2.3.5] at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:232) ~[jaxb-runtime-2.3.5.jar:2.3.5] at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:227) ~[jaxb-runtime-2.3.5.jar:2.3.5] at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:94) ~[jaxb-runtime-2.3.5.jar:2.3.5] at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1117) ~[jaxb-runtime-2.3.5.jar:2.3.5] at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:542) ~[jaxb-runtime-2.3.5.jar:2.3.5] at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:524) ~[jaxb-runtime-2.3.5.jar:2.3.5] at com.sun.xml.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:137) ~[jaxb-runtime-2.3.5.jar:2.3.5] at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source) ~[xercesImpl-2.12.2.jar:?] at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source) ~[xercesImpl-2.12.2.jar:2.12.2] at org.apache.xerces.impl.XMLNSDocumentScannerImpl$NSContentDispatcher.scanRootElementHook(Unknown Source) ~[xercesImpl-2.12.2.jar:2.12.2] at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source) ~[xercesImpl-2.12.2.jar:2.12.2] at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source) ~[xercesImpl-2.12.2.jar:2.12.2] at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source) ~[xercesImpl-2.12.2.jar:?] at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source) ~[xercesImpl-2.12.2.jar:?] at org.apache.xerces.parsers.XMLParser.parse(Unknown Source) ~[xercesImpl-2.12.2.jar:?] at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source) ~[xercesImpl-2.12.2.jar:?] at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source) ~[xercesImpl-2.12.2.jar:?] at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:228) ~[jaxb-runtime-2.3.5.jar:2.3.5] at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:199) ~[jaxb-runtime-2.3.5.jar:2.3.5] at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:157) ~[?:1.8.0_342] at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:162) ~[?:1.8.0_342] at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:171) ~[?:1.8.0_342] at com.myproject.integrationtest.server.ws.NetworkWebServiceTest.convertXMLToObject(NetworkWebServiceTest.java:106) ~[test-classes/:?] at com.myproject.integrationtest.server.ws.NetworkWebServiceTest.should_throw_exception_with_error_message_when_execute_operation_with_corrupted_parameter2(NetworkWebServiceTest.java:98) ~[test-classes/:?] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_342] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_342] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_342] at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_342] at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59) ~[junit-4.13.2.jar:4.13.2] at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56) ~[junit-4.13.2.jar:4.13.2] at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) ~[junit-4.13.2.jar:4.13.2] at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) ~[junit-4.13.2.jar:4.13.2] at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306) ~[junit-4.13.2.jar:4.13.2] at org.junit.runners.ParentRunner.run(ParentRunner.java:413) ~[junit-4.13.2.jar:4.13.2] at org.junit.runner.JUnitCore.run(JUnitCore.java:137) ~[junit-4.13.2.jar:4.13.2] at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69) ~[junit-rt.jar:?] at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38) ~[junit-rt.jar:?] at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11) ~[idea_rt.jar:?] at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35) ~[junit-rt.jar:?] at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:232) ~[junit-rt.jar:?] at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55) ~[junit-rt.jar:?]
解决方法
方案一:修改XML匹配POJO配置
JAXB期望带命名空间urn:com.myproject.server.ws.dto.cfg且首字母大写的<Network>元素,当前XML根元素是无命名空间的小写<network>。修改后的XML如下:
<Network xmlns="urn:com.myproject.server.ws.dto.cfg"> <supportedFeatures> <nmsDiversity>ENABLE</nmsDiversity> <fullSiteDiversity>ENABLE</fullSiteDiversity> </supportedFeatures> <fullSiteDiversity> <activeDc>DC2</activeDc> <active1NGw>My_Teleport_5_GW_Main</active1NGw> </fullSiteDiversity> </Network>
子元素会自动继承根元素的命名空间,无需单独声明。
方案二:修改POJO适配现有XML
如果无法修改XML,可调整POJO的JAXB注解,去掉命名空间并将元素名改为小写:
@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "network") @XmlType(name = "network") public class Network { @NotNull @Valid private NetworkSupportedFeaturesSection supportedFeatures; @Valid private NetworkFullSiteDiversitySection fullSiteDiversity; // getter和setter方法保持不变 }
同时需确保关联的POJO(如NetworkSupportedFeaturesSection)也去掉命名空间,并将对应元素名改为小写(比如@XmlRootElement(name = "supportedFeatures"))。
方案三:忽略命名空间差异(临时兼容)
如需临时兼容无命名空间的XML,可通过设置Unmarshaller属性忽略命名空间,但可能引发其他兼容性问题,仅作临时方案:
private static Optional<Network> convertXMLToObject(URL url) { try { JAXBContext context = JAXBContext.newInstance(Network.class); Unmarshaller un = context.createUnmarshaller(); // 忽略命名空间 un.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapper() { @Override public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { return ""; } }); return Optional.of((Network) un.unmarshal(url)); } catch (JAXBException e) { LOGGER.error(e.getMessage(), e); } return Optional.empty(); }
内容的提问来源于stack exchange,提问作者Alexei
相关产品推荐
相关产品推荐

