我有一些JAXB类应该映射XML,这些XML可能包含它应该保留的未知元素。
我为此创建了一个小型测试用例,其中包含两个类Thing
和Subthing
,其中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
}