2016-01-25 18 views
12

Xét đoạn mã sau:Serialize JAXB POJO nhiều hoặc khác nhau namespace

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; 

Tôi muốn tái sử dụng các POJO khách hàng và tạo ra hai giá trị không gian tên khác nhau. Vì vậy, đầu tiên tôi muốn in đầu ra

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

như mã hiện có, sau đó tạo ra một xml thứ hai với một không gian tên chính khác với POJO tương tự mà sẽ trông như thế này

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

hoặc loại bỏ các không gian tên tất cả cùng nhau

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<customer> 
    <id>123</id> 
</customer> 
+0

Bạn nên thực hiện một đoạn mã thêm cho * @ XMLSCHEMA * phần vì nó là rất có liên quan , nhưng có thể dễ dàng bị bỏ qua. – jah

Trả lời

7

Đây là một câu hỏi hay.

Thay vì làm việc ở cấp loại bạn có thể làm việc ở cấp độ nút Jaxb. Có gần như không có chi phí liên quan.

Điều quan trọng là tạo/truy cập JAXBElement (yếu tố cấp nút) trong các lớp logic nghiệp vụ của bạn và tùy chỉnh nút XML mà nó đại diện với định nghĩa theo định nghĩa QName.

QName cung cấp một số tùy chọn để tùy chỉnh, từ các không gian tên hoàn toàn đủ điều kiện đến không có không gian tên nào cả. Thông báo trước duy nhất là việc sử dụng không gian tên không có tiền tố là không thể. Jaxb sẽ sử dụng một không gian tên mặc định nếu bạn không cung cấp.

Ví dụ:

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); 

này sẽ cho kết quả sau:

<?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> 

Sử dụng một namespace prefix mà không là không thể. Cố gắng một QName với trống tiền tố hoặc tương đương XMLConstants.DEFAULT_NS_PREFIX như tham số sẽ dẫn đến một tiền tố mặc định (như ns1) được tạo ra:

// 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> 

Sử dụng rỗng như các tham số cho prefix mang một ngoại lệ:

java.lang.IllegalArgumentException: prefix cannot be "null" when creating a QName 
at javax.xml.namespace.QName.<init>(QName.java:251) 
+0

package-info.java nằm bên trong ví dụ, nó được tạo tự động bằng công cụ jaxb – danidacar

+1

Nếu bạn có ảnh hưởng đến quá trình tạo JAXB của mình, bạn có thể thử bỏ qua thế hệ package-info.java (thông qua tùy chọn -xpa của xjc) – jah

3

Làm thế nào để ghi đè lên các rễ thuộc tính xmlns với MOXY:

EclipseLink MOXy cung cấp tùy chỉnh dễ dàng cho việc sửa lỗi JAXB, bao gồm thay đổi không gian tên mặc định của phần tử gốc của bạn. Các đối tượng để lập bản đồ XML (OXM) cho trọng không gian tên mặc định là:

<?xml version="1.0"?> 
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" version="2.5"> 
    <xml-schema element-form-default="QUALIFIED" namespace="http://www.another.org/package"/> 
</xml-bindings> 

Để không có không gian tên mặc định, sử dụng <xml-schema element-form-default="UNSET"/> để thay thế.

MOXY Setup:

1) thêm thư viện để dự án của bạn:

<dependency> 
    <groupId>org.eclipse.persistence</groupId> 
    <artifactId>org.eclipse.persistence.moxy</artifactId> 
    <version>2.6.2</version> 
</dependency> 

2) Thêm một jaxb.properties để gói mô hình đối tượng của bạn để cho phép nhà máy MOXY của (ví dụsrc/main/resources/com/sample/entity/jaxb.properties):

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory 

3) Khởi tạo con của bạn văn bản theo cấu hình OXM của bạn (trong ví dụ này, file OXM làsrc/main/resources/com/sample/entity/my-oxm.xml):

Map<String, Source> metadata = Collections.singletonMap("com.sample.entity", new StreamSource(Customer.class.getResourceAsStream("my-oxm.xml"))); 
Map<String, Object> properties = Collections.singletonMap(JAXBContextProperties.OXM_METADATA_SOURCE, metadata); 
JAXBContext jaxbContext = JAXBContext.newInstance(new Class[] {customer.getClass()}, properties); 

Sau đó bạn có thể sử dụng marshalling trên JAXBContext như bình thường. Khởi tạo các bối cảnh riêng biệt cho từng tệp OXM khác nhau mà bạn muốn sử dụng.

tùy chỉnh bổ sung với MOXY:

Sử dụng MOXY cho phép bạn tùy chỉnh thêm các marshalling của tổ chức của bạn trong tương lai mà không thay đổi mô hình đối tượng của bạn, có hiệu quả làm luận marshalling bạn tuân thủ các open/closed principle ngay cả khi bạn không có các lớp học Marshaller rõ ràng. Ví dụ, nếu bạn cần để marshal đối tượng Customer bạn như là một Person, bạn có thể làm điều này bằng cách thêm một file OXM:

<?xml version="1.0"?> 
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm" version="2.5"> 
    <xml-schema element-form-default="QUALIFIED" namespace="http://www.example.com/person"/> 
    <java-types> 
     <java-type name="com.sample.entity.Customer"> 
      <xml-root-element name="person"/> 
      <java-attributes> 
       <xml-attribute java-attribute="id" name="personId"/> 
       <xml-element java-attribute="id" xml-path="someOtherId/text()"/> 
      </java-attributes> 
     </java-type> 
    </java-types> 
</xml-bindings> 
Các vấn đề liên quan