将Jaxb Pojos序列化为多个或不同的名称空间

dan*_*car 12 java xml xsd jaxb marshalling

请考虑以下代码:

Main.java
====
package com.sample;

import com.sample.entity.Customer;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class Main {    

    public static void main(String[] args) throws JAXBException {
       JAXBContext jc = JAXBContext.newInstance(Customer.class);

       Customer customer = new Customer();
       customer.setId(123);

       Marshaller m = jc.createMarshaller();
       m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
       m.marshal(customer, System.out);    
    }
}


Customer.java
====
package com.sample.entity;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Customer {
    private long id;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }
}

package-info.java
====
@XmlSchema(namespace = "http://www.example.org/package", elementFormDefault = XmlNsForm.QUALIFIED)
package com.sample.entity;

import javax.xml.bind.annotation.XmlSchema;
import javax.xml.bind.annotation.XmlNsForm;
Run Code Online (Sandbox Code Playgroud)

我希望重用Customer POJO并创建两个不同的命名空间值.所以首先我想打印输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer xmlns="http://www.example.org/package">
    <id>123</id>
</customer>
Run Code Online (Sandbox Code Playgroud)

就像当前代码一样,然后创建第二个xml,其中包含来自同一个pojo的不同主命名空间,如下所示

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer xmlns="http://www.another.org/package">
    <id>123</id>
</customer>
Run Code Online (Sandbox Code Playgroud)

或者一起删除命名空间

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer>
    <id>123</id>
</customer>
Run Code Online (Sandbox Code Playgroud)

jah*_*jah 7

这是一个很好的问题.

您可以在Jaxb节点级别上工作,而不是在类型级别上工作.几乎没有任何开销.

关键是JAXBElement从业务逻辑类中创建/访问(节点级元素),并使用相应的QName定义自定义它所代表的XML节点.

QName提供了几个自定义选项,从完全限定的命名空间到根本没有命名空间.唯一需要注意的是,使用不带前缀的命名空间是不可能的.如果您不提供默认命名空间,Jaxb将使用默认命名空间.

示例:

QName elaborateQName = new QName("http://www.another.org/package", "customer", "myNs");
QName simpleQName = new QName("customer");

JAXBElement jx1 = new JAXBElement(elaborateQName, customer.getClass(), customer);
JAXBElement jx2 = new JAXBElement(simpleQName, customer.getClass(), customer);

m.marshal(jx1, System.out);
m.marshal(jx2, System.out);
Run Code Online (Sandbox Code Playgroud)

这将产生以下输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<myNs:customer xmlns:myNs="http://www.another.org/package">
    <id>123</id>
</myNs:customer>

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer>
    <id>123</id>
</customer>
Run Code Online (Sandbox Code Playgroud)

使用不带前缀的命名空间是不可能的.尝试使用空前缀或等效XMLConstants.DEFAULT_NS_PREFIX参数的QName 将导致生成默认前缀(如ns1):

 // QName defaultNs = new QName("http://www.another.org/package", "customer", "");

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:customer xmlns:ns1="http://www.another.org/package">
    <id>123</id>
</ns2:customer>
Run Code Online (Sandbox Code Playgroud)

使用null作为参数prefix产生异常:

java.lang.IllegalArgumentException: prefix cannot be "null" when creating a QName
at javax.xml.namespace.QName.<init>(QName.java:251)
Run Code Online (Sandbox Code Playgroud)