[英]Jaxb and namespace of inner element
我遇到了一个看起来很简单但解决起来并不明显的问题。
我有 2 个包,它们的类编组为 xml 并具有不同的命名空间。 一个 class 是其他人的容器。
package namespace1;
@XmlRootElement(name = "container", namespace = "urn:nmsp:container:001.02")
@XmlAccessorType(XmlAccessType.FIELD)
@Getter
@Setter
public class Container {
@XmlElement(name = "name")
private String name;
@XmlElement(name = "messages")
private List<Message> messages;
}
-------------------------------------------
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Message", propOrder = {
"document"
})
public class Message {
@XmlElement(name = "Document", namespace = "urn:iso:std:iso:20022:001", required = true)
protected Document document;
}
-------------------------------------------
package-info.java
@javax.xml.bind.annotation.XmlSchema(namespace = "urn:nmsp:container:001.02",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns = {
@XmlNs(namespaceURI = "urn:nmsp:container:001.02", prefix = "")
})
package namespace1;
和
package namespace2;
@XmlRootElement(name = "document", namespace = "urn:iso:std:iso:20022:001")
@XmlAccessorType(XmlAccessType.FIELD)
public class Document {
@XmlElement(name = "id")
private String id;
}
package-info.java
@javax.xml.bind.annotation.XmlSchema(namespace = "urn:iso:std:iso:20022:001",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns = {
@XmlNs(namespaceURI = "urn:iso:std:iso:20022:001", prefix = "")
})
package namespace2;
我想得到的是:
<container xmlns="urn:nmsp:container:001.02">
<name>Hello</name>
<messages>
<Document xmlns="urn:iso:std:iso:20022:001">
<id>ID1</id>
</Document>
</messages>
</container>
但我得到的是:
<container xmlns="urn:nmsp:container:001.02" xmlns:ns2="urn:iso:std:iso:20022:001">
<name>Hello</name>
<messages>
<ns2:Document>
<ns2:id>ID1</ns2:id>
</ns2:Document>
</messages>
</container>
编组代码为:
Container conxml = new Container("Hello");
conxml.setMessages(List.of(new Message(new Document("ID1")))));
JAXBContext jc = JAXBContext.newInstance(Container.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter writer = new StringWriter();
QName _Conxml_QNAME = new QName("urn:nmsp:container:001.02", "container");
JAXBElement<Container> conxmlJAXBElement = new JAXBElement<>(_Conxml_QNAME, Container.class, null, conxml);
marshaller.marshal(conxmlJAXBElement, writer);
System.out.println(writer.toString());
几乎所有解决方案都建议使用 package-info.java 修复它,但实际上并没有帮助。 你能告诉我我做错了什么吗?
maven 项目的链接: JaxbTest.7z
您提供的两个 XML 文件是等效的,您选择命名空间声明是一个品味问题。 在为每个命名空间选择前缀时,会考虑您在@XmlNs
注释中设置的前缀。 但是,至少 JAXB RI 不会在文档中间重新定义它们。
如果您想更直接地干预 XML 的生成方式,则需要在 JAXB 和Writer
之间添加额外的组件。 例如,您可以使用 StAX 并将您的文档编组到像这样的XMLStreamWriter ( IndentingXMLStreamWriter
来自 TXW2,JAXB RI 的依赖项):
private static class RedefineNsXmlStreamWriter extends IndentingXMLStreamWriter {
@Override
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
final String known_prefix = getNamespaceContext().getPrefix(namespaceURI);
super.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, localName, namespaceURI);
if (!XMLConstants.DEFAULT_NS_PREFIX.equals(known_prefix)) {
super.writeNamespace(XMLConstants.DEFAULT_NS_PREFIX, namespaceURI);
}
}
@Override
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
// Ignore it
}
public RedefineNsXmlStreamWriter(XMLStreamWriter out) {
super(out);
}
}
然后创建一个能够写入Writer
并序列化的XMLStreamWriter
:
final XMLStreamWriter xmlWriter = new RedefineNsXmlStreamWriter(XMLOutputFactory.newFactory()//
.createXMLStreamWriter(writerCont));
marshallerCont.marshal(conxmlJAXBElement, xmlWriter);
当然,一旦考虑到所有情况, RedefineNsXmlStreamWriter
会变得更加复杂,但它适用于您的示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.