2013-03-23 126 views
1

我想解開以前編組的XML。JAXB Unmarshal - 缺少元素和元素不按順序排列

在unmarshalled結果中,我缺少元素,而我得到的元素與輸入XML的順序不同。我創建了一個afterUnmarshal()偵聽器,並且我看到了那裏的元素,但沒有看到最終的Java對象。

的XSD的結構是這樣的(A「fanout'節點,例如,可以含有另一組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()輸出:

[email protected][[email protected][endpointRef=Step6.EP, type=SERVICE, params=<null>, paramsRef=<null>, name=Step6, description=<null>], stepOrFanoutOrDecision={[email protected][option={[email protected][[email protected][endpointRef=Step2a.EP, type=SERVICE, params=<null>, paramsRef=<null>, name=Step 2A, description=<null>], stepOrFanoutOrDecision=<null>, name=op1],[email protected][[email protected][endpointRef=Step2a.EP, type=SERVICE, params=<null>, paramsRef=<null>, name=Step 2B, description=<null>], stepOrFanoutOrDecision=<null>, name=op2]}, name=Decision-nonameneeded, description=<null>],[email protected][path={[email protected][[email protected][endpointRef=Step4A.EP, type=SERVICE, params=<null>, paramsRef=<null>, name=Step4A, description=<null>], stepOrFanoutOrDecision=<null>, name=<null>],[email protected][[email protected][endpointRef=Step5.EP, type=SERVICE, params=<null>, paramsRef=<null>, name=Step5, description=<null>], stepOrFanoutOrDecision=<null>, name=<null>]}, name=Fan1, description=<null>]}] 

螞蟻我使用的腳本:與擴展的hashCode,和的toString等於:

<?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> 
+0

相應的JAXB對象是什麼樣子的? – 2013-03-23 19:56:04

+0

我添加了更多信息 - 我希望吸引您的注意力:),我在您的博客上閱讀了一些條目,但找不到我想要的內容。 – PhilW 2013-03-23 21:20:20

+0

您是否從XML架構生成模型? – 2013-03-23 21:42:04

回答

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; 

    ... 
} 

SOLUTION

可以使用simple binding mode擴展在JAXB XJC工具來支持這種使用情況。它會自動阻止創建step屬性。您可以通過如下所示的外部綁定文檔來指定:

綁定。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 
+0

謝謝。那麼你會說這是一個限制JAXB?它本質上是一種具有3種節點的樹,它們可以包含相同的節點,但每個分支的第一個節點必須是「step」類型。 您會做什麼?(我可以自由選擇任何其他方法框架等)) – PhilW 2013-03-25 15:31:28

+0

@PhilW - 我已經更新了我的答案,以及如何使用內置的XJC擴展來處理這個問題 – 2013-03-25 16:04:49

+1

非常感謝!我已經試過了,它使我的代碼更易於讀寫。現在也可以創建一個根據XSD無效的對象(過程中的第一項行程必須是step類型的,而不是決定或扇出)。我相信你知道這一點,但我認爲這可能是對他人的興趣 再次感謝你,我保存了幾天的工作。 – PhilW 2013-03-27 22:16:57