JAXB 和命名空间相关问题
JAXB and namespaces related issue
编组 JAXB class 后,我有以下 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 class 中的 元素声明为:
@XmlAnyElement(lax = true)
@XmlElementRefs({
@XmlElementRef(name="Another", type=Another.class, required=false)
})
protected List<Object> any;
它可能包含数量未知的其他元素,这些元素具有自己的命名空间。
问题:
当我编组 Some.class 对象时,jaxb 将 Another.class 的名称空间作为 ns0 放入根元素中,因为我从另一个方法中将 编组为 Element他们的命名空间包括在内我不需要它再次进入根元素。
这是一个问题,因为 不是必需的,所以如果我用空列表编组 Some.class 对象,我将始终拥有 xmlns:ns0.
我需要 @XmlElementRefs 和 @XmlElementRef 注释,因为我需要从 json 转换为 XML 并且 Jackson 需要知道 "any" 列表可能具有的类型。
我如何告诉 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 class 来包装 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 名称空间,希望这对某人有所帮助。
编组 JAXB class 后,我有以下 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 class 中的
@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 需要知道 "any" 列表可能具有的类型。
我如何告诉 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 class 来包装 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 名称空间,希望这对某人有所帮助。