供应商提供的XML如下:
<?xml version="1.0" encoding="utf-8"?>
<Foo>
<Bar>...</Bar>
<Bar>...</Bar>
</Foo>
请注意,没有xmlns="..."
声明,供应商也不提供架构。这无法更改,供应商将来会继续像这样发布XML。
为了生成JAXB绑定,我创建了一个这样的模式:
<?xml version="1.0" encoding="utf-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://acme.com/schema"
xmlns:tns="http://acme.com/schema"
elementFormDefault="qualified">
<xsd:element name="Foo">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="tns:Bar" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="Bar">
...
</xsd:element>
</xsd:schema>
请注意,我已经声明了一个或多或少有意义的命名空间(&#34; http://acme.com/schema&#34;),以便它可以用于元素引用等.XJC生成以下{{ 1}}:
package-info.java
然后我尝试解组XML文档:
@javax.xml.bind.annotation.XmlSchema(namespace = "http://acme.com/schema", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package com.acme.schema;
这是我得到的例外:
JAXBContext jaxb = JAXBContext.newInstance("com.acme.schema");
Unmarshaller unmarshaller = jaxb.createUnmarshaller();
InputStream is = this.getClass().getClassLoader().getResourceAsStream("test.xml");
InputSource source = new InputSource(is);
Foo foo = (Foo) unmarshaller.unmarshal(source);
显然,这是因为XML元素属于空命名空间,而JAXB类属于非空元素。
有没有办法伪造XML命名空间(可能在XML解析期间),以便JAXB识别元素并成功绑定它们? SAX / StAX解决方案比DOM更受欢迎,因为XML文档可能相当庞大。
答案 0 :(得分:2)
首先,我不推荐所有这些。与第三方API集成非常复杂,无需添加额外的复杂功能。为什么要添加命名空间呢?我不知道你从中得到了什么。想想那些继承你的代码库的幸运者。他们会看到添加名称空间,但不知道你为什么要这样做。
我甚至会更进一步,建议完全避免使用模式,只使用带注释的POJO。所有这些步骤只会增加复杂性,构建步骤等。
但是,如果你确定了,这似乎是XSL转换的典型案例。您可以找到一个足够容易添加名称空间的XSL转换,例如this question那么将转换连接到JAXB就很简单......
private static Foo unmarshalDocument(InputStream xslStream, InputStream xmlStream) throws Exception {
StreamSource stylesource = new StreamSource(xslStream);
StreamSource inputStream = new StreamSource(xmlStream);
Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource);
JAXBResult result = new JAXBResult(context);
transformer.transform(inputStream, result);
return (Foo) result.getResult();
}