1

我有一些 JAXB 类应该映射可能包含它应该保留的未知元素的 XML。

我为此创建了一个带有两个类的小测试用例ThingSubthing其中Thing还有一个@XmlAnyElement List<Element>属性。

源 XML,添加了换行和缩进以提高可读性:

<a:thing xmlns:a="some:uri:a">
  <a:subthing val="1"/>
  <div xmlns="http://www.w3.org/1999/xhtml">
    <p/>
  </div>
  <b:something xmlns:b="some:uri:b"/>
</a:thing>

解组和编组后的结果,再次格式化以提高可读性:

<a:thing xmlns:a="some:uri:a">
  <a:subthing val="1"/>
  <div:div xmlns="http://www.w3.org/1999/xhtml"
           xmlns:div="http://www.w3.org/1999/xhtml">
    <p/>
  </div:div>
  <b:something xmlns:b="some:uri:b"/>
</a:thing>

请注意,div 元素现在有一个 div 命名空间前缀和相应的属性。它是有效的并且等效于输入,但我不相信以后应该使用它的任何东西都会正确处理它(特别是因为在这种情况下它是 html(即使它是 xhtml),但它也可能是其他东西)。

我使用调试器检查了未编组的对象,并且 DOM 元素没有前缀,因此编组器似乎添加了此前缀。

有什么办法可以防止这种情况发生吗?

完整来源:

package-info.java

@XmlSchema(namespace = "some:uri:a", xmlns = {
        @XmlNs(prefix = "a", namespaceURI = "some:uri:a")
})
package p;

import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlSchema;

Thing.java

package p;

import org.w3c.dom.Element;

import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;

@XmlRootElement(namespace = "some:uri:a")
public class Thing {
    @XmlElement(namespace = "some:uri:a")
    public Subthing subthing;

    @XmlAnyElement
    public List<Element> other; 
}

Subthing.java

package p;

import javax.xml.bind.annotation.XmlAttribute;

class Subthing {
    @XmlAttribute
    public int val;
}

Test case (groovy syntax):

    @Test
    void opaqueXMLNamespaceHandling2() {
        def xml = '<a:thing xmlns:a="some:uri:a"><a:subthing val="1"/><div xmlns="http://www.w3.org/1999/xhtml"><p/></div><b:something xmlns:b="some:uri:b"/></a:thing>'
        JAXBContext ctx = JAXBContext.newInstance(Thing.class, Subthing.class);
        Unmarshaller unmarshaller = ctx.createUnmarshaller();
        def thing = (Thing) unmarshaller.unmarshal(new StringReader(xml));
        println thing.subthing.val
        Marshaller m = ctx.createMarshaller();
        m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        StringWriter sw = new StringWriter();
        m.marshal(thing, sw)
        println sw.toString()
        thing = (Thing) unmarshaller.unmarshal(new StringReader(sw.toString()));
        println thing.subthing.val
    }
4

0 回答 0