如果未设置命名空间前缀,则解组对象为空

Unmarshalled object is null if namespace prefix is not set

我有以下 XSD:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:x="MY_NAMESPACE"
           targetNamespace="MY_NAMESPACE">

    <xs:element name="response" type="x:responseType"/>

    <xs:complexType name="responseType">
        <xs:all>
            <xs:element name="param" type="x:responseParam"/>
        </xs:all>
    </xs:complexType>

    <xs:complexType name="responseParam">
        <xs:all>
            <xs:element name="value" type="xs:string"/>
        </xs:all>
    </xs:complexType>

</xs:schema>

我用它来生成 JAXB 类 来解组有效负载,如下所示:

<x:response xmlns:x="MY_NAMESPACE">
<param>
<value>OK</value>
</param>
</x:response>

通过 getWebServiceTemplate().marshalSendAndReceive 在 Spring 中。问题是,我还想解组没有命名空间前缀的有效负载,如下所示:

<response xmlns="MY_NAMESPACE">
<param>
<value>OK</value>
</param>
</response>

在这种情况下,response 标记被正确解析,但表示 param 的对象引用始终为 null。我怎样才能编辑我的 XSD 以使其正常工作?我已经尝试在架构中设置 elementFormDefault="qualified",甚至在 param 元素上设置 form="qualified"

想到的其他信息(我可能会根据评论进行编辑和添加):

XML 个文件

我想您可能知道这一点,但是删除该命名空间前缀会影响整个文档(因为 'param' 和 'value' 标记没有任何前缀,因此会继承默认的命名空间绑定)。因此,在第一个文档中,根标签 'response' 位于命名空间 'MY_NAMESPACE' 中,而其他标签没有任何命名空间。在第二个文档中,所有标签都在命名空间 'MY_NAMESPACE'.

XML 架构

elementFormDefault 属性默认为 'unqualified',因此您的架构应匹配第一个文档并拒绝第二个。你的实验证实了这一点。 如果将 elementFormDefault 设置为 'qualified' 那么它将拒绝第一个文档并匹配第二个文档。 没有使 XSD 匹配两个 XML 文档的 elementFormDefault 值。名称空间是元素标识的组成部分。

可能的解决方案

如果您决定构建一个匹配两个文档的XSD,那么可以按如下方式完成:

  • 将 elementFormDefault 显式设置为 'unqualified'(可选,但您将依赖该设置)b
  • 将 responseType 的当前(全局声明的)内容包装在一个选择组中
  • 在选择组中添加第二个分支,其中包含元素 'param' 及其所有后代的 local 声明。因为它们是在本地声明的,所以它们将在 noTargetNamespace 中。

这不是使 JAXB 忽略命名空间问题的通用解决方案,我认为您不会找到一个解决方案(尽管我很高兴被比我更了解 JAXB 的人纠正) .

综上所述...我认为您可能正在解决错误的问题。 JAXB 标准基于 XML 架构。 XSD 并不意味着容忍错误的命名空间。因此,第二个 XML 文档无效,应该由生成它的人更正。