JAXB Unmarshal - 缺少元素,元素不​​按顺序排列

时间:2013-03-23 19:16:54

标签: jaxb jaxb2

我正在尝试解组之前编组过的XML。

在unmarshalled结果中,我缺少元素,我得到的元素与输入XML的顺序不同。我创建了一个afterUnmarshal()侦听器,我在那里看到了元素,但是在生成的Java对象中没有。

XSD的结构如下(例如,'扇出'节点可以包含另一组processSteps,因此它可以深度嵌套(树)):

<xsd:element name="process">
        <xsd:annotation>
            <xsd:documentation>Integration Process</xsd:documentation>
        </xsd:annotation>
        <xsd:complexType>
            <xsd:sequence>
        <!-- more -->
                <xsd:element name="itinerary" type="lwis:itineraryType"/>
        <!-- more -->
        </xsd:complexType>
    </xsd:element>
    <xsd:complexType name="itineraryType">
        <xsd:sequence>
            <xsd:element name="step" type="lwis:stepType"/>
            <xsd:choice minOccurs="0" maxOccurs="unbounded">
                <xsd:element name="step" type="lwis:stepType"/>
                <xsd:element name="fanout" type="lwis:fanoutType"/>
                <xsd:element name="decision">
                    <xsd:complexType>
                            <!-- snip.. -->
                    </xsd:complexType>
                </xsd:element>
            </xsd:choice>
        </xsd:sequence>
    </xsd:complexType>

我想订单是由SAX解析器给出的,但我无法想象SAX解析器会无缘无故地改变顺序?目前,列表中的第一个元素是XML中的最后一个元素。列表中的第二个元素是XML中的第三个元素 - 它似乎是随机的..

感谢您的帮助!

示例输入:

<?xml version="1.0" encoding="ISO-8859-1" standalone="yes"?>
<process name="My.Process" description="My Process description" qualityOfService="AT_LEAST_ONCE" entryEndpoint="ENTRY.EP" xmlns="http://www.xxxxx.com/ns/yyyy">
    <faultEndpoint endpoint_ref="EXIT.EP"/>
    <rejectEndpoint endpoint_ref="EXIT.EP"/>
    <itinerary>
        <step name="Step 1" endpoint_ref="Step1.EP" type="SERVICE"/>
        <step name="Step2-CBRStep" endpoint_ref="Step2.EP" type="SERVICE"/>
        <decision name="Decision-nonameneeded">
            <option name="op1">
                <step name="Step 2A" endpoint_ref="Step2a.EP" type="SERVICE"/>
            </option>
            <option name="op2">
                <step name="Step 2B" endpoint_ref="Step2a.EP" type="SERVICE"/>
            </option>
        </decision>
        <step name="Step 3" endpoint_ref="Step3.EP" type="SERVICE"/>
        <fanout name="Fan1">
            <path>
                <step name="Step4A" endpoint_ref="Step4A.EP" type="SERVICE"/>
            </path>
            <path>
                <step name="Step4B" endpoint_ref="Step4B.EP" type="SERVICE"/>
                <step name="Step5" endpoint_ref="Step5.EP" type="SERVICE"/>
            </path>
        </fanout>
        <step name="Step6" endpoint_ref="Step6.EP" type="SERVICE"/>
    </itinerary>
</process>

对象:

Process Object has a field with itinerary of Type ItineraryType which:
step = StepType ("Step6" from XML)
stepOrFanoutOrDecision = ArrayList:
 item 0: ItineraryType$Decision ("Decision-nonameneeded" from XML)
   option 0: "op1" from XML
     step: "Step 2A" from XML
   option 1: "op2" from XML
     step: "Step 2B" from XML
 item 1: FanoutType ("Fan1" from XML)
     path 0: 
      step: Step4A
     path 1: 
      step: Step5

步骤1,步骤2-CBRStep和步骤4B丢失了?

我在这里有行程的toString()输出:

com.x.ItineraryType@fe39ebf[step=com.x.StepType@28cb15bf[endpointRef=Step6.EP, type=SERVICE, params=<null>, paramsRef=<null>, name=Step6, description=<null>], stepOrFanoutOrDecision={com.x.ItineraryType$Decision@2d00c385[option={com.x.ItineraryType$Decision$Option@d2467d8[step=com.x.StepType@511d9ca5[endpointRef=Step2a.EP, type=SERVICE, params=<null>, paramsRef=<null>, name=Step 2A, description=<null>], stepOrFanoutOrDecision=<null>, name=op1],com.x.ItineraryType$Decision$Option@6f173e3d[step=com.x.StepType@5ef74fc5[endpointRef=Step2a.EP, type=SERVICE, params=<null>, paramsRef=<null>, name=Step 2B, description=<null>], stepOrFanoutOrDecision=<null>, name=op2]}, name=Decision-nonameneeded, description=<null>],com.x.FanoutType@3e963f38[path={com.x.FanoutType$Path@7a1095a1[step=com.x.StepType@56cfbba2[endpointRef=Step4A.EP, type=SERVICE, params=<null>, paramsRef=<null>, name=Step4A, description=<null>], stepOrFanoutOrDecision=<null>, name=<null>],com.x.FanoutType$Path@6027b534[step=com.x.StepType@4ee99a3d[endpointRef=Step5.EP, type=SERVICE, params=<null>, paramsRef=<null>, name=Step5, description=<null>], stepOrFanoutOrDecision=<null>, name=<null>]}, name=Fan1, description=<null>]}]

我正在使用的Ant脚本:扩展名为hashCode,toString和equals:

<?xml version="1.0" encoding="UTF-8"?>
<project name="RunningXjc" default="generate-sources" basedir=".">
    <description>Runs Xjc Binding Compiler</description>

    <target name="generate-sources">
        <taskdef name="xjc" classname="org.jvnet.jaxb2_commons.xjc.XJC2Task">
            <classpath>
                <fileset dir="buildLib/jaxb-ri-2.2.6/lib">
                    <include name="*" />
                </fileset>
                <fileset dir="buildLib/jaxb2-basics-dist-0.6.4/dist">
                    <include name="jaxb2-basics-ant-*.jar" />
                </fileset>
            </classpath>
        </taskdef>

        <!-- Generate the Java code for XSD -->
        <xjc destdir="${basedir}/target/generated-sources/xjc" extension="true">
            <arg
                line="
        -Xequals
        -XhashCode
        -XtoString
        -Xcopyable
        -Xmergeable" />
            <binding dir="${basedir}/src">
                <include name="**/*.xjb" />
            </binding>
            <schema dir="${basedir}/schema">
                <include name="processSlim.xsd" />
            </schema>
            <!-- Plugins -->
            <classpath>
                <fileset dir="${basedir}/buildLib/jaxb2-basics-dist-0.6.4">
                    <!-- JAXB2 Basics library -->
                    <include name="dist/jaxb2-basics-*.jar" />
                    <!-- JAXB2 Basics library dependencies -->
                    <include name="dist/jaxb2-basics-runtime-*.jar" />
                    <include name="dist/jaxb2-basics-tools-*.jar" />
                    <include name="lib/commons-beanutils-*.jar" />
                    <include name="lib/commons-lang-*.jar" />
                    <include name="lib/commons-logging-*.jar" />
                    <include name="lib/javaparser-*.jar" />
                    <include name="lib/annox-*.jar" />
                </fileset>
            </classpath>
        </xjc>
    </target>
</project>

1 个答案:

答案 0 :(得分:1)

<强>问题

来自您的XML架构

以下是XML架构中的一个片段。 itineraryType包含一个序列,其中step元素可以在选择结构的内部和外部出现。

<xsd:complexType name="itineraryType">
    <xsd:sequence>
        <xsd:element name="step" type="lwis:stepType" />
        <xsd:choice minOccurs="0" maxOccurs="unbounded">
            <xsd:element name="step" type="lwis:stepType" />
            <xsd:element name="fanout" type="lwis:fanoutType" />
            <xsd:element name="decision">
                <xsd:complexType>
                    <!-- snip.. -->
                </xsd:complexType>
            </xsd:element>
        </xsd:choice>
    </xsd:sequence>
</xsd:complexType>

<强> ItineraryType

这导致step元素映射到导致您出现问题的两个不同属性。

public class ItineraryType {

    @XmlElement(required = true)
    protected StepType step;
    @XmlElements({
        @XmlElement(name = "step", type = StepType.class),
        @XmlElement(name = "fanout", type = FanoutType.class),
        @XmlElement(name = "decision", type = ItineraryType.Decision.class)
    })
    protected List<Object> stepOrFanoutOrDecision;

   ...
}

<强>解

您可以使用JAXB XJC工具中的simple binding mode扩展名来支持此用例。它将自动阻止创建step属性。您可以通过外部绑定文档指定此项,如下所示:

<强> bindings.xml

<jxb:bindings 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    jxb:extensionBindingPrefixes="xjc"
    version="2.1">


    <jxb:globalBindings>
        <xjc:simple />
    </jxb:globalBindings>

</jxb:bindings>

XJC致电

以下是在XJC调用中引用外部绑定文件的方法。您还需要使用-extension标志来启用XJC扩展。

xjc -extension -b bindings.xml schema.xsd