我有以下 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>
通过Spring中的getWebServiceTemplate().marshalSendAndReceive
。问题是,我还想在没有命名空间前缀的情况下解码有效负载,如下所示:
<response xmlns="MY_NAMESPACE">
<param>
<value>OK</value>
</param>
</response>
在这种情况下,response
标记已正确解析,但表示 param
的对象引用始终为 null。如何编辑 XSD 才能正常工作?我已经尝试在架构中设置 elementFormDefault="qualified"
,甚至在 param
元素上设置 form="qualified"
。
想到的其他信息(我可能会根据评论编辑和添加更多信息):
- 解码器是一个
Jaxb2Marshaller
。
最佳答案
XML 文档
我想您可能知道这一点,但是删除该 namespace 前缀会影响整个文档(因为“param”和“value”标签没有任何前缀,因此继承默认 namespace 绑定(bind))。因此,在第一个文档中,根标签“response”位于命名空间“MY_NAMESPACE”中,而其他标签没有任何命名空间。在第二个文档中,所有标记都位于命名空间“MY_NAMESPACE”中。
XML 架构
elementFormDefault 属性默认为“unqualified”,因此您的架构应匹配第一个文档并拒绝第二个文档。你的实验证实了这一点。 如果您将 elementFormDefault 设置为“qualified”,那么它将拒绝第一个文档并匹配第二个文档。 elementFormDefault 没有任何值可以使 XSD 与两个 XML 文档相匹配。命名空间是元素标识的一个组成部分。
可能的解决方案
如果您决定构建一个与两个文档都匹配的 XSD,则可以按如下方式完成:
- 将 elementFormDefault 显式设置为“不合格”(可选,但您将依赖该设置)b
- 将responseType的当前(全局声明)内容包装在选择组中
- 在选择组中添加第二个分支,其中包含元素“param”及其所有后代的本地声明。因为它们是本地声明的,所以它们将位于 noTargetNamespace 中。
这不是使 JAXB 忽略命名空间问题的通用解决方案,我认为您不会找到一个解决方案(尽管我很高兴被比我更了解 JAXB 的人纠正)。
说了以上所有内容...我认为您可能正在解决错误的问题。 JAXB 标准基于 XML 架构。 XSD 并不意味着容忍错误的 namespace 。因此,第二个 XML 文档无效,应该由生成它的人进行更正。
关于java - 如果未设置命名空间前缀,则解码对象为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59143372/