如果未设置命名空间前缀,则解组对象为空
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"
。
想到的其他信息(我可能会根据评论进行编辑和添加):
- 解组程序是
Jaxb2Marshaller
。
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 文档无效,应该由生成它的人更正。
我有以下 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"
。
想到的其他信息(我可能会根据评论进行编辑和添加):
- 解组程序是
Jaxb2Marshaller
。
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 文档无效,应该由生成它的人更正。