我们正在使用xjc生成用于XML生成的JAXB Java类。除了我们尝试调整生成的名称空间前缀as described here之外,一切正常。由于我们正在使用的JAXB版本,我们坚持使用“解决方案2”,调整package-info.java。
我们的结构是几个深度导入:root命名空间导入其他命名空间,而后者又导入第三个命名空间。
MCVE xsds
root.xsd(import other.xsd):
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="root" xmlns:other="other" targetNamespace="root" version="1.0">
<xs:import namespace="other" schemaLocation="other.xsd" />
<xs:element name="rootElem">
<xs:complexType>
<xs:choice>
<xs:element ref="rootElem1"/>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="rootElem1" nillable="false">
<xs:complexType>
<xs:sequence>
<xs:element name="data">
<xs:complexType>
<xs:choice>
<xs:element ref="other:otherElem"/>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
other.xsd(import third.xsd):
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:other="other" xmlns:third="third" targetNamespace="other" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0">
<xsd:import namespace="third" schemaLocation="third.xsd" />
<xsd:element name="otherElem">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="third:thirdElem" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
third.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:third="third" targetNamespace="third" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.0">
<xsd:element name="thirdElem">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="thirdData" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
有了这个
简单的测试用例
@Test
public void test() throws JAXBException
{
Marshaller marshaller = JAXBContext.newInstance("test.jaxb.generated").createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.example.com/schema.xsd");
RootElem root = new RootElem();
RootElem1 root1 = new RootElem1();
Data d = new Data();
OtherElem other = new OtherElem();
ThirdElem thirdElem = new ThirdElem();
thirdElem.setThirdData("third");
other.setThirdElem(thirdElem);
d.setOtherElem(other);
root1.setData(d);
root.setRootElem1(root1);
Path path = Paths.get("target", "outfile.xml");
Result result = new StreamResult(path.toFile());
marshaller.marshal(root, result);
}
这导致了这个
生成的XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns4:rootElem xmlns:ns2="other" xmlns:ns3="third" xmlns:ns4="root" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/schema.xsd">
<ns4:rootElem1>
<data>
<ns2:otherElem>
<ns3:thirdElem>
<ns3:thirdData>third</ns3:thirdData>
</ns3:thirdElem>
</ns2:otherElem>
</data>
</ns4:rootElem1>
</ns4:rootElem>
并且一切正常(除了data
之外没有任何关联的命名空间,我假设因为这是一个内部类型)。
现在这部分是问题:这是
生成了package-info.java
@javax.xml.bind.annotation.XmlSchema(namespace = "other", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package test.jaxb.generated;
为什么namespace
指的是other
?我的根命名空间是root
。 (root.xsd
是我们给Maven jaxb2-maven-plugin
的唯一文件;我们可以包含其他文件,但没有区别。)
错误的替换package-info.java
如果我们用这个覆盖生成的那个:
@javax.xml.bind.annotation.XmlSchema(
namespace = "root",
xmlns = {
@javax.xml.bind.annotation.XmlNs(prefix = "t", namespaceURI = "third"),
@javax.xml.bind.annotation.XmlNs(prefix = "o", namespaceURI = "other"),
@javax.xml.bind.annotation.XmlNs(prefix = "r", namespaceURI = "root")
},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package test.jaxb.generated;
我们最初做的是因为我们假设我们必须在这里给出根名称空间 - 这是
错误生成的XML
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<r:rootElem xmlns:t="third" xmlns:o="other" xmlns:r="root" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/schema.xsd">
<r:rootElem1>
<data>
<r:otherElem>
<t:thirdElem>
<t:thirdData>third</t:thirdData>
</t:thirdElem>
</r:otherElem>
</data>
</r:rootElem1>
</r:rootElem>
现在命名空间很漂亮,但错了! otherElem
属于o
,而非r
。
将覆盖文件中的命名空间更改回other
可修复错误,但同样重复:
问题是为什么所需的命名空间other
在这里?同样令人困惑的是,third
导入的图层无论如何都是正确的。
问题已解决,但我们想了解这个概念。我们缺少什么?
编辑:
为了完整起见,这是build
的{{1}}部分:
pom.xml
答案 0 :(得分:2)
问题是您在一个包中生成所有类(使用Maven插件的packageName
配置。
不要这样做。
JAXB在某种程度上基于包命名空间对应的概念。您使用的每个命名空间应该有一个包。虽然技术上可行,否则你将面临一个接一个的问题。因此,最好遵循这个概念,并为每个命名空间使用或生成一个包。您仍然可以配置目标程序包 - 但使用绑定文件而不是插件配置元素。