【发布时间】:2023-03-11 10:19:01
【问题描述】:
我正在尝试编写一个 Java 11 XML 解组器,它在将命名空间数据转换为对象之前将其剥离,但出现以下错误。应用程序需要先从所有元素中剥离出前面的app:,然后才能被强制转换为 Object。
如何使用 JDK11 做到这一点?
错误
javax.xml.bind.UnmarshalException
- with linked exception:
[com.sun.istack.SAXParseException2; lineNumber: 2; columnNumber: 67; unexpected element (uri:"", local:"app:exampleXML"). Expected elements are <{http://www.example.com/schemas/app}object>]
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.handleStreamException(UnmarshallerImpl.java:453)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:387)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:356)
XmlUnmarshaller.unmarshal(XmlUnmarshaller.java:36)
...
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: com.sun.istack.SAXParseException2; lineNumber: 2; columnNumber: 67; unexpected element (uri:"", local:"app:exampleXML"). Expected elements are <{http://www.example.com/schemas/app}object>
...
... 20 more
Caused by: javax.xml.bind.UnmarshalException: unexpected element (uri:"", local:"app:exampleXML"). Expected elements are <{http://www.example.com/schemas/app}object>
... 31 more
测试
public void testUnmarshal() throws JAXBException, XMLStreamException {
String xml3 = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
"<app:exampleXML xmlns:app=\"http://www.example.com/schemas/app\">\n" +
"<app:id>app-id</app:id>\n" +
"<app:time>2020-06-05T13:17:00.899Z</app:time>\n" +
"<app:type>test</app:type>\n" +
"<app:description>Test</app:description>\n" +
"</app:exampleXML>";
XmlUnmarshaller unmarshaller = new XmlUnmarshaller();
Object object = unmarshaller.unmarshal(xml3, Object.class);
System.out.println(object);
}
解组器
public <T> T unmarshal(String xml, Class<T> clazz) throws JAXBException, XMLStreamException {
JAXBContext jc = JAXBContext.newInstance(clazz);
XMLInputFactory xif = XMLInputFactory.newFactory();
xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
StreamSource source = new StreamSource(new StringReader(xml));
XMLStreamReader xsr = xif.createXMLStreamReader(source);
return clazz.cast(unmarshaller.unmarshal(xsr));
}
对象
@XmlRootElement(name = "exampleXML", namespace="http://www.example.com/schemas/app")
@XmlAccessorType(XmlAccessType.FIELD)
public class XML {
public static final int DESCRIPTION_LENGTH = 4000;
@XmlElement(name = "id", required = true)
private String id;
@XmlElement(name = "time", required = true)
@XmlJavaTypeAdapter(InstantXmlAdapter.class)
@JsonSerialize(using = InstantJsonSerializer.class)
@JsonDeserialize(using = InstantJsonDeserializer.class)
private Instant time;
@XmlElement(name = "type", required = true)
private CheckpointLevel type;
@XmlElement(name = "description")
@XmlJavaTypeAdapter(CDATAXmlAdapter.class)
private String description;
【问题讨论】:
-
将app命名空间与默认绑定相同。
-
@ThorbjørnRavnAndersen 你这是什么意思?我已经在对象上的
XMLRootElement中分配了命名空间(请参阅更新) -
请解释您为什么要这样做。编写使用命名空间的 Java 代码很容易。
-
@kimbert 因为解组仅适用于没有
app:命名空间的 XML。有没有更好的方法在维护命名空间的同时将此 xml 数据强制转换为我的对象?
标签: java xml jaxb unmarshalling java-11