如何将名称空间定义从根元素移动到 JAXB 中的特定子元素?

How can I move the namespace definition from the root element to a specific child in JAXB?

提问人:molfo 提问时间:8/23/2023 最后编辑:journpymolfo 更新时间:8/24/2023 访问量:47

问:

我正在开发一个 Java 应用程序,它使用 JAXB 将 Java 对象封送到 XML 中。目前,生成的 XML 如下所示:

<A xmlns="A" xmlns:ns2="B" xmlns:ns3="C">
<t1>content</t1>
<t2>
    <ns2:t3>
        <ns2:t4>content2</ns2:t4>           
    </ns2:t3>       
</t2>
</A>

命名空间定义放置在根标记“A”中。此外,一些命名空间(例如“C”)甚至没有使用。我想将命名空间定义放在内部子项中,而不是前缀。例如,我想获取以下 xml:

<A xmlns="A">
<t1>content</t1>
<t2 xmlns:ns2="B">
    <t3>
        <t4>content2</t4>           
    </t3>       
</t2>
</A>

这两个 xml 都是有效的,但我需要生成第二个输出才能通过第三方应用程序的验证。

我怎样才能做到这一点?

谢谢。

Java XML 名称空间 JAXB 接组

评论


答:

0赞 Karsten 8/23/2023 #1

请注意,仅将命名空间与前缀相关联。具有此前缀的任何元素都将属于关联的命名空间。不带前缀的元素属于默认命名空间。xmlns:name="..."

因此。。。

  • 在第一个示例中,从未使用过命名空间 C。
  • 在第二个示例中,唯一使用的命名空间是默认命名空间,因为这两个元素都没有前缀。

除此之外,将命名空间声明放在哪里并不重要,只要在需要时声明它们即可。

<A xmlns="A" xmlns:ns2="B">
<t1>content</t1>
<t2>
    <ns2:t3>
        <ns2:t4>content2</ns2:t4>           
    </ns2:t3>       
</t2>
</A>

相当于

<A xmlns="A">
<t1>content</t1>
<t2>
    <ns2:t3 xmlns:ns2="B">
        <ns2:t4>content2</ns2:t4>           
    </ns2:t3>       
</t2>
</A>

使用 JAXB 时,您必须使用 XmlElement 注释来定义名称空间:

@XmlElement(name = "t3", namespace = "B")
protected T3 t3;

对应属于此命名空间的任何其他元素重复此操作。

编辑

我尝试使用两个模式和一个测试XML文件重新创建问题:

架构 1

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:b="http://karsten/B"
           targetNamespace="http://karsten/B"
           elementFormDefault="qualified">
           
    <xs:complexType name="Wrapper">
        <xs:sequence>
            <xs:element name="Child" type="b:Child"/>
        </xs:sequence>
    </xs:complexType>
    
    <xs:complexType name="Child">
        <xs:attribute name="id" type="xs:integer"/>
    </xs:complexType>

</xs:schema>

和架构 2

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:b="http://karsten/B">

    <xs:import schemaLocation="namespaces-experiment-core.xsd" namespace="http://karsten/B"/>
    
    <xs:element name="Root">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Wrapper" type="b:Wrapper"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>

</xs:schema>

此 XML 文档成功验证了架构,尽管 Child-elements 的命名空间是在根级别声明的。如果它移动到 Child-element,它仍然有效。

<Root xmlns:b="http://karsten/B"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="namespaces-experiment-wrapper.xsd"
   xsi:schemaLocation="http://karsten/B namespaces-experiment-core.xsd"
   >
   
    <Wrapper>
        <b:Child id="1"/>
    </Wrapper>
    
</Root>

评论

0赞 molfo 8/23/2023
我已经尝试在注释中指定命名空间,但 JAXB 无论如何都将 xmlns 放在根目录中@XmlElement
0赞 Karsten 8/23/2023
啊,现在我明白了。对于任何标准的共形 XML 解析器,命名空间是在文档的根元素上声明还是在使用之前的任何路径上都无关紧要。因此,JAXB 将无法改变其行为。因此,要么您遇到一个非共形的 XML 解析器/验证器,要么问题可能出在其他一些(例如父元素的命名空间)上。您无法从第三方应用程序获取XML架构吗?
0赞 molfo 8/24/2023
是的,我从它们提供的模式自动生成了 JAXB 类。不幸的是,当我封送对象时,所有命名空间都放在顶部
0赞 Karsten 8/24/2023
看我的编辑。我无法想象标准的共形 XML 解析器坚持将命名空间放在子元素上。