在编码 JAXB 类后,我有以下 XML:
<?xml version="1.0" encoding="UTF-8"?>
<foo:Object xsi:schemaLocation="http://foo.com/ http://foo.com/foo.xsd"
xmlns:ns0="http://lipsum.com/bar" xmlns:foo="http://foo.com/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<foo:Some attr1="601"/>
<foo:Others>
<bar:Another xsi:schemaLocation="http://lipsum.com/bar
http://lipsum.com/bar.xsd" xmlns:bar="http://lipsum.com/bar">
<bar:SomeOther attr2="01"/>
</bar:Another>
</foo:Others>
</foo:Object>
jaxb 类中的
@XmlAnyElement(lax = true)
@XmlElementRefs({
@XmlElementRef(name="Another", type=Another.class, required=false)
})
protected List<Object> any;
它可能包含未知数量的其他具有自己命名空间的元素。
问题:
当我编码 Some.class 对象时,jaxb 将 Another.class 的命名空间作为 ns0 放入根元素中,因为我从另一个方法中将
这是一个问题,因为
我需要 @XmlElementRefs 和 @XmlElementRef 注释,因为我需要从 json 转换为 XML,而 Jackson 需要知道“任何”列表可能具有的类型。
我如何告诉 JAXB Oracle/Moxy 实现:
1.- Ignore the namespaces from @XmlElementRef classes during the marshalling.
2.- Remove the not used namespaces aka NS[0-9] prefixes from the root element.
任何帮助将不胜感激。
最佳答案
以防万一有人需要这个,我有办法删除不需要的命名空间,这个技巧是从 XMLStreamWriter 提供的
步骤 1.- 创建一个 WrapperXMLStreamWriter 类,用于包装 XMLStreamWriter。
public class WrapperXMLStreamWriter implements XMLStreamWriter {
private final XMLStreamWriter writer;
public WrapperXMLStreamWriter(XMLStreamWriter writer) {
this.writer = writer;
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamWriter#writeStartElement(java.lang.String)
*/
@Override
public void writeStartElement(String localName) throws XMLStreamException {
// for each overloaded method call to writer do the method
writer.writeStartElement(localName);
}
/* (non-Javadoc)
* @see javax.xml.stream.XMLStreamWriter#writeNamespace(java.lang.String, java.lang.String)
*/
@Override
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
// Here is the trick
if(!prefix.startsWith("ns")){
writer.writeNamespace(prefix, namespaceURI);
}
}
...
}
步骤 2.- 像往常一样创建编码器
Map<String,String> prefixes = new HashMap<String, String>();
//
prefixes.put("http://www.w3.org/2001/XMLSchema-instance","xsi");
prefixes.put("http://foo.com/", "foo");
Marshaller marshaller = AppContextTool.getInstance().getContextForFoo().createMarshaller();
//
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapperImpl(prefixes));
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://foo.com/ http://foo.com/foo.xsd");
3.- 使用第一步的给定 XMLStreamWriter 编码 Foo 实例
Foo foo = new Foo();
ByteArrayOutputStream xml= new ByteArrayOutputStream();
try {
XMLStreamWriter writer =
new WrapperXMLStreamWriter((XMLStreamWriter) XMLOutputFactory.newInstance().createXMLStreamWriter(xml, "UTF-8"));
marshaller.marshal(foo, writer);
} catch (XMLStreamException | FactoryConfigurationError e) {
e.printStackTrace();
}
4.- 结果:
<?xml version="1.0" encoding="UTF-8"?>
<foo:Object xsi:schemaLocation="http://foo.com/ http://foo.com/foo.xsd"
xmlns:foo="http://foo.com/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<foo:Some attr1="601"/>
<foo:Others>
<bar:Another xsi:schemaLocation="http://lipsum.com/bar
http://lipsum.com/bar.xsd" xmlns:bar="http://lipsum.com/bar">
<bar:SomeOther attr2="01"/>
</bar:Another>
</foo:Others>
</foo:Object>
没有更多的 NS 命名空间,希望这对某人有所帮助。
关于xml - JAXB 和命名空间相关问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47356420/