JAXB unmarshal正在跳过具有其他命名空间的元素

时间:2016-11-09 21:45:33

标签: java xml jaxb

自从我调试JAXB解组以来已经好几年了。我发现正确解析了带有命名空间的有效XML文档的情况,但是当代码将文档解组成对象时,对象中的某些属性不会被设置,从而使它们保持为空。我可以单步执行代码,但是一旦进入jaxb解组,就很难跟上它所做的事情。它似乎直接在JAXB类的实例上设置实例变量(设置为FIELD),因此我不能在setter中设置断点以查看它何时(或者是否)设置特定属性。

我可以使用一些提示来了解如何在解组过程中获得更多诊断,以查看它可能出错的地方。

正在解析的XML文档相对简单。它是一个SOAP信封,解组是在身体的第一个孩子身上完成的。

有问题的子元素指定了两个名称空间,一个是周围元素的默认名称空间,另一个是在某些子元素中引用的非默认名称空间。它实际上来自非默认命名空间的所有元素在解组结果中都以null结尾。我认为这是一个重要线索,但我不能从中说出错误。

对于一些成员,SOAP主体的第一个孩子看起来像这样:

<validationResponse xmlns="http://.../ValidationResponse.xsd" xmlns:dm="http://.../DataModel.xsd">
<indicator>true</indicator>
<MatchedAddressResult>
<AddressMatchResult>
<dm:Address>
<dm:Street>
<dm:streetNumber>10000</dm:streetNumber>
<dm:streetName>ELM</dm:streetName>
<dm:streetType>ST</dm:streetType>
</dm:Street>
<dm:Unit>
<dm:type>APT</dm:type>
<dm:value>2033</dm:value>
</dm:Unit>
<dm:city>NOWHERE</dm:city>
<dm:state>TX</dm:state>
<dm:Zip>
<dm:zipCode>11111</dm:zipCode>
<dm:zipCodeExtension>2740</dm:zipCodeExtension>
</dm:Zip>
<dm:county>NOWHERE</dm:county>
</dm:Address>
<dm:cassAddress>
<dm:addressLine>10000 ELM ST APT 2033</dm:addressLine>
<dm:addressLine>NOWHERE TX  11111-2740</dm:addressLine>
</dm:cassAddress>
<dm:addressMatchCode>4S80</dm:addressMatchCode>
<dm:isAddressException>false</dm:isAddressException>
</AddressMatchResult>
</MatchedAddressResult>
<Response>
<dm:code>0</dm:code>
<dm:description>Success</dm:description>
</Response>
</validationResponse>

JAXB类的顶部如下所示:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name="ValidateAddressResponseInfo", propOrder={"matchedAddressIndicator", "matchedAddressResult", "response"})
public class ValidationResponseInfo implements Serializable
{
  protected boolean matchedAddressIndicator;
  @XmlElement(name="MatchedAddressResult")
  protected MatchedAddressResult matchedAddressResult;
  @XmlElement(name="Response", required=true)
  protected ResponseInfo response;

  @XmlAccessorType(XmlAccessType.FIELD)
  @XmlType(name="", propOrder={"exactMatchLocation", "alternativeLocation", "addressMatchResult"})
  public static class MatchedAddressResult
    implements Serializable
  {
    @XmlElement(name="ExactMatchLocation")
    protected ExactMatchLocation exactMatchLocation;

    @XmlElement(name="AlternativeLocation")
    protected AlternativeLocation alternativeLocation;

    @XmlElement(name="AddressMatchResult")
    protected List<AddressValidationResultInfo> addressMatchResult;

同样,所有映射到&#34; dm&#34;的字段前缀结束为null。不知何故,解组并没有映射这些属性。

更新

以下是相关元素的架构摘录。

  <xs:complexType name='AddressValidationResultInfo'>
    <xs:sequence>
      <xs:element name='Address'>
        <xs:complexType>
          <xs:complexContent>
            <xs:extension base='AddressUnrestrictedInfo'>
              <xs:sequence>
                <xs:element name='addressType' type='AddressTypeInfo' minOccurs='0'/>
              </xs:sequence>
            </xs:extension>
          </xs:complexContent>
        </xs:complexType>
      </xs:element>
      <xs:element name='cassAddress' type='CassAddressInfo' minOccurs='0'/>
      <xs:element name='addressMatchCode' type='xs:string' minOccurs='0'>
      </xs:element>
      <xs:element name='addressMatchDescription' type='xs:string' minOccurs='0'>
      </xs:element>
      <xs:element name='addressId' type='FiberServiceAddressIdInfo' minOccurs='0'>
      </xs:element>
      <xs:element name='exchangeCode' type='FiberServiceExchangeCodeInfo' minOccurs='0'>
      </xs:element>
      <xs:element name='isAddressException' type='xs:boolean'>
      </xs:element>
      <xs:element name='addressExceptionCode' type='xs:string' minOccurs='0'>
      </xs:element>
      <xs:element name='addressExceptionDescription' type='xs:string' minOccurs='0'>
      </xs:element>
      <xs:element name='crossBoundaryState' type='CrossBoundaryStateInfo' minOccurs='0'>
      </xs:element>
      <xs:element name='confidence' type='xs:long' minOccurs='0'>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name='AddressUnrestrictedInfo'>
    <xs:sequence>
      <xs:element name='attention' type='xs:string' minOccurs='0'/>
      <xs:element name='addressLine1' type='AddressLineInfo' minOccurs='0'>
      </xs:element>
      <xs:element name='addressLine2' type='AddressLineInfo' minOccurs='0'>
      </xs:element>
      <xs:element name='Street' type='AddressStreetUnrestrictedInfo' minOccurs='0'/>
      <xs:element name='Elevation' type='AddressAttributeInfo' minOccurs='0'>
      </xs:element>
      <xs:element name='Structure' type='AddressAttributeInfo' minOccurs='0'>
      </xs:element>
      <xs:element name='Unit' type='AddressAttributeInfo' minOccurs='0'>
      </xs:element>
      <xs:element name='postOfficeBox' type='xs:string' minOccurs='0'/>
      <xs:element name='RuralRoute' minOccurs='0'>
        <xs:complexType>
          <xs:sequence>
            <xs:element name='ruralRouteCenterNumber' type='xs:string'/>
            <xs:element name='ruralRouteBoxNumber' type='xs:string'/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name='city' type='AddressCityInfo' minOccurs='0'/>
      <xs:element name='state' type='AddressStateInfo' minOccurs='0'/>
      <xs:element name='Zip' type='AddressZipInfo' minOccurs='0'/>
      <xs:element name='country' type='xs:string' minOccurs='0'/>
      <xs:element name='county' type='xs:string' minOccurs='0'>
      </xs:element>
      <xs:element name='countyCode' minOccurs='0'>
        <xs:simpleType>
          <xs:restriction base='xs:string'>
            <xs:maxLength value='3'/>
          </xs:restriction>
        </xs:simpleType>
      </xs:element>
      <xs:element name='urbanizationCode' type='AddressUrbanizationInfo' minOccurs='0'/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name='AddressStreetUnrestrictedInfo'>
    <xs:sequence>
      <xs:element name='streetNumberPrefix' type='xs:string' minOccurs='0'>
      </xs:element>
      <xs:element name='streetNumber' type='xs:string' minOccurs='0'>
      </xs:element>
      <xs:element name='streetNumberSuffix' type='xs:string' minOccurs='0'>
      </xs:element>
      <xs:element name='streetDirection' type='xs:string' minOccurs='0'>
      </xs:element>
      <xs:element name='streetName' type='xs:string' minOccurs='0'/>
      <xs:element name='streetType' type='xs:string' minOccurs='0'>
      </xs:element>
      <xs:element name='streetTrailingDirection' type='xs:string' minOccurs='0'>
      </xs:element>
      <xs:element name='assignedStreetNumber' type='xs:string' minOccurs='0'>
      </xs:element>
    </xs:sequence>
  </xs:complexType>

2 个答案:

答案 0 :(得分:0)

检查您的XSD架构和生成的类 问题在这里:
JAXB期望AddressMatchResult为List,  但XML中没有任何东西可以满足它 在XML中,有一个元素为

<AddressMatchResult>
  <dm:Address>
  <dm:Street>

... 因此,对应于AddressMatchResult类必须具有Address,Street等直接属性。  根据现有的XSD更正XSD并重新生成JAXB或更正XML

答案 1 :(得分:0)

  

实际上,所有元素都来自非默认元素   在unmarshalled结果中以null结尾的名称空间。我想   这是一个重要的线索,但我无法分辨出那是什么问题。

确实,这可能是。

在soap消息中为dm prexif引用的xmlns是在xsd中声明的吗? 不要犹豫,显示xsd文件,它可能会有所帮助。

  

同样,映射到“dm”前缀的所有字段都以null结尾。不知何故   解组不会映射这些属性。

它给人的印象是在解组时无法识别命名空间 命名空间在jaxb元素中并不精确。所以我想它是在package-info.java文件中声明的。

你能检查用于带有dm前缀的元素的命名空间是否是预期的,它位于合适的包中:

@javax.xml.bind.annotation.XmlSchema (
    namespace = "yourRealNamespaceForDn",
    elementFormDefault=javax.xml.bind.annotation.XmlNsForm.QUALIFIED
)

如果一切正常,另一种解决问题的方法就是通过编写一个简单的单元测试来隔离它,该单元测试使用jaxb反序列化和你在输入中提取的xml以及输出中预期的创建对象。 尝试通过指定名称空间属性(例如:

)在jaxb元素中使用名称空间声明
@XmlType(namespace="yourNamespace", name="", propOrder={"exactMatchLocation", "alternativeLocation", "addressMatchResult"})
  public static class MatchedAddressResult ...