繁体   English   中英

Jaxb 和内部元素的命名空间

[英]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 并将您的文档编组到像这样的XMLStreamWriterIndentingXMLStreamWriter来自 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM