【问题标题】:JAXB unmarshal is skipping elements with other namespaceJAXB unmarshal 正在跳过具有其他命名空间的元素
【发布时间】:2016-11-09 21:45:33
【问题描述】:

我已经有好几年没有调试 JAXB 解组了。我看到了这样一种情况,即正确解析了具有名称空间的有效 XML 文档,但是当代码将文档解组为对象时,对象中的某些属性未设置,使它们为空。我可以单步执行代码,但是一旦进入 jaxb 解组,就很难理解它在做什么。它似乎直接在 JAXB 类的实例上设置实例变量(设置为 FIELD),因此我无法在设置器中设置断点以查看它何时(或是否)设置特定属性。

我可以使用一些提示来了解如何对解组过程进行更多诊断,以查看可能出现的问题。

被解析的 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;

同样,映射到“dm”前缀的所有字段最终都为空。不知何故,解组并没有映射这些属性。

更新

这里是相关元素的架构摘录。

  <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>

【问题讨论】:

    标签: java xml jaxb


    【解决方案1】:

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

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

    ... 所以对应的AddressMatchResult类必须有Address、Street等直接属性。 更正 XSD 并重新生成 JAXB 或根据现有 XSD 更正 XML

    【讨论】:

    • 您如何建议我“根据现有 XSD 更正 XML”?
    • 嗨大卫,问题是你如何获得 thos dm:elements 的空值(即地址、街道等?
    • 查看 JAXB 类,我认为它应该是这样的: addressMatchResult.getAddressValidationResultInfo.get(0).getAddress() 如果是这样,您可以尝试将 AddressMatchResult 中的所有内容包装到 <AddressValidationResultInfo&gt ;标签
    【解决方案2】:

    其实就是所有非默认的元素 在未编组的结果中最终为 null 的命名空间。我想 这是一条重要的线索,但我不知道其中有什么问题。

    确实如此。

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

    同样,映射到“dm”前缀的所有字段最终都为空。不知何故 解组不会映射这些属性。

    它给人的印象是在解组期间无法识别命名空间。
    命名空间在 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 ...
    

    【讨论】:

    • 我无法修改 JAXB 类。请注意,我确实单步执行了解析器,我看到它解析了“xmlns:dm”属性并存储了该命名空间的信息。我不知道你所说的“你能检查一下使用的命名空间......”是什么意思。
    • 所以我意识到您指的是检查相关“package-info”文件的内容。当我在 XML 中指定时,我能够验证为 ValidationResponseInfo 和 AddressValidationResultInfo 指定的命名空间是否匹配。
    • 您能否发布 MatchedAddressResult 的 XSD 定义片段、其类型以及 AddressValidationResultInfo 的片段?
    • 顺便说一句,如果您有 XSD,您可以在单独的项目中生成 JAXB 类,仅用于测试目的。
    猜你喜欢
    • 2020-11-30
    • 1970-01-01
    • 2021-04-24
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    • 2011-10-17
    相关资源
    最近更新 更多