我们有一个客户端正在发送从两个单独的模式生成的xml消息。
我们希望在单个应用程序中处理它们,因为内容是相关的。
我们无法修改用于生成XML消息的客户端架构......
我们可以修改我们自己的两个模式(或binding.jxb)的副本 - 如果有帮助 - 为了启用JAXB处理从两个独立模式创建的消息。
不幸的是,两个模式都具有相同的根元素名称(见下文)。
问题:JAXB是否完全禁止处理具有相同根元素名称的两个模式? - 如果是这样,我会阻止我的“复活节彩蛋”寻找解决方案...... ---或者,是否有一些解决方法可以让我们使用JAXB处理从两个不同模式生成的这些XML消息?
schema1(注意根元素名称:“A”):
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:element name="A">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="AA">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="AAA1" type="xsd:string" />
<xsd:element name="AAA2" type="xsd:string" />
<xsd:element name="AAA3" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="BB">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="BBB1" type="xsd:string" />
<xsd:element name="BBB2" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
schema2(再次注意,使用相同的根元素名称:“A”)
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:element name="A">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="CCC">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="DDD1" type="xsd:string" />
<xsd:element name="DDD2" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="EEE">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="EEE1">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="FFF1" type="xsd:string" />
<xsd:element name="FFF2" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="EEE2" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
答案 0 :(得分:1)
问题:JAXB是否禁止 绝对处理两个模式 具有相同的根元素名称?
解答:您可以使用相同的根元素映射多个类,但是您需要在解组操作上指定类型。
<强> A1 强>
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="A")
public class A1 {
}
<强> A2 强>
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="A")
public class A2 {
}
<强> input.xml中强>
<A/>
<强>演示强>
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(A1.class, A2.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xmlFile = new File("input.xml");
StreamSource xmlSource = new StreamSource(xmlFile);
A1 a1 = unmarshaller.unmarshal(xmlSource, A1.class).getValue();
Marshaller marshaller = jc.createMarshaller();
marshaller.marshal(a1, System.out);
}
}
更多信息:
以下是一个示例绑定文件,可用于自定义元素映射到的类。我没有看到两个模式之间有任何关系。你是否以某种方式组合它们是一个单一的XJC操作?
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jxb:bindings schemaLocation="schema1.xsd">
<jxb:bindings node="//xs:element[@name='A']">
<jxb:class name="RenamedA"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
答案 1 :(得分:1)
我尝试将前面建议的两个模式(使用相同的元素名称)组合在一起。
(注意:我必须使用“回答您自己的问题”发布以包含示例,因为评论只允许有限的空间)
我遇到的一个问题是实际模式中的一些子元素(我无法发布实际的模式)使用相同的名称(我必须在下面重新创建,以说明这种情况... - 通知schema1和schema2“group”包含具有相同名称的元素)...
这是schemacombo.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:group name="schema1">
<xs:sequence>
<xs:element name="AA">
<xs:complexType>
<xs:sequence>
<xs:element name="CC1" type="xs:string"/>
<xs:element name="CC2" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="BB">
<xs:complexType>
<xs:sequence>
<xs:element name="DD1" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:group>
<xs:group name="schema2">
<xs:sequence>
<xs:element name="AA">
<xs:complexType>
<xs:sequence>
<xs:element name="CC1" type="xs:string"/>
<xs:element name="CC2" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="BB">
<xs:complexType>
<xs:sequence>
<xs:element name="DD1">
<xs:complexType>
<xs:sequence>
<xs:element name="EE1" type="xs:string"/>
<xs:element name="EE2" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:group>
<xs:element name="A">
<xs:complexType>
<xs:choice>
<xs:group ref="schema1" />
<xs:group ref="schema2" />
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
我试过了
xjc schemacombo.xsd -b binding.xjb
... binding.xjb包含
<?xml version="1.0" encoding="UTF-8"?>
<jxb:bindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
jaxb:version="2.0">
<jxb:bindings schemaLocation = "schemacombo.xsd" node="/xs:schema">>
<jxb:schemaBindings>
<jxb:bindings node="xs:group[@name='schema2']">
<jxb:nameXmlTransform>
<jxb:modelGroupName suffix="2"/>
</jxb:nameXmlTransform>
</jxb:bindings>
</jxb:schemaBindings>
</jxb:bindings>
</jxb:bindings>
...-我知道这是一次微弱的尝试,而且它不起作用......即,运行它会产生:
parsing a schema...
[ERROR] cos-element-consistent: Error for type '#AnonType_A'. Multiple elements with name 'AA', with different types, appear in the model group.
line 49 of file:/C:/AAAAA_delegate/schemacombo.xsd
[ERROR] cos-nonambig: AA and AA (or elements from their substitution group) violate "Unique Particle Attribution". During validation against this schema, ambiguity would be created for those two particles.
line 49 of file:/C:/AAAAA_delegate/schemacombo.xsd
Failed to parse a schema.
您是否有任何关于修复此问题的绑定语句或注释的建议。 - 注意,我还没有看到定制的绑定工作。
答案 2 :(得分:0)
遗憾的是,问题不在于根元素都具有相同的名称,而是它们被定义为完全相同的元素 - 意思是相同的名称和相同的名称空间。你无法以你想要的方式处理这些模式。
你能做什么,虽然它确实意味着你需要做很多维护工作,然后利用选择和组引用将两个模式的定义组合成一个定义,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:group name="schema1a">
<xsd:sequence>
<xsd:element name="AA">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="AAA1" type="xsd:string" />
<xsd:element name="AAA2" type="xsd:string" />
<xsd:element name="AAA3" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="BB">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="BBB1" type="xsd:string" />
<xsd:element name="BBB2" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:group>
<xsd:group name="schema2a">
<xsd:sequence>
<xsd:element name="CCC">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="DDD1" type="xsd:string" />
<xsd:element name="DDD2" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="EEE">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="EEE1">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="FFF1" type="xsd:string" />
<xsd:element name="FFF2" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="EEE2" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:group>
<xsd:element name="A">
<xsd:complexType>
<xsd:choice>
<xsd:group ref="schema1a" />
<xsd:group ref="schema2a" />
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
基本上我们采用每个模式的A元素的复杂类型定义并将它们更改为组定义,然后我们将这些组定义包含在choice元素中。这将有效地允许jaxb解析器正确处理使用任一模式生成的文档。在任一模式的更新之间维护这一点是很多工作..但也许这可以使用XSLT和一些脚本自动化。
希望这会有所帮助