如何使用JAXB处理来自两个单独模式的消息(具有相同的元素名称)

时间:2011-03-09 17:41:31

标签: jaxb

我们有一个客户端正在发送从两个单独的模式生成的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>

3 个答案:

答案 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和一些脚本自动化。

希望这会有所帮助