具有默认命名空间的JAXB @XmlAnyElement在编组时添加前缀

时间:2014-03-07 11:00:18

标签: java xml jaxb xmlanyelement

我有一些JAXB类应该映射XML,这些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),但它也可能是其他东西)。

我使用调试器检查了unmarshalled对象,并且DOM元素没有前缀,因此marshaller似乎添加了这个前缀。

有没有办法阻止这种情况?

完整来源:

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
    }

0 个答案:

没有答案