2011-05-16 75 views
5

我有問題unmarshall下面嵌套的xml。有人可以請告知我是否缺少一些東西。
body標記可以包含任何Jaxb anotated obj。
我是否必須創建一個自定義適配器來編組/解組這樣的xml?Jaxb複雜xml unmarshall

輸入XML

<?xml version="1.0" encoding="UTF-8"?> 
<serviceRq xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="serviceRq"> 
    <body> 
    <createRq> 
     <id>1234</id> 
    </createRq> 
    </body> 
</serviceRq> 

我JAXB註釋類:

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "serviceRq") 
public class ServiceRq{  
    private Object body; 
    <!-- getters and setters omitted--> 
} 

這裏,主體可以是任何JAXB註釋對象,在這種情況下,它CreateRq。

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "createRq") 
public class CreateRq{  
    private String id; 
    <!-- getters and setters omitted--> 
} 

我正在尋找一種通用的方式來支持輸入xml正文中的任何Jaxb註釋對象。

回答

6

你可以使用一個@XmlAnyElement(lax=true)XmlAdapter以處理這個用例:

ServiceRq

import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlType; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "serviceRq") 
public class ServiceRq{  

    @XmlJavaTypeAdapter(value=BodyAdapter.class) 
    private Object body; 
    // getters and setters omitted 
} 

BodyAdapter

import javax.xml.bind.annotation.adapters.XmlAdapter; 

public class BodyAdapter extends XmlAdapter<Body, Object>{ 

    @Override 
    public Object unmarshal(Body v) throws Exception { 
     return v.getValue(); 
    } 

    @Override 
    public Body marshal(Object v) throws Exception { 
     Body body = new Body(); 
     body.setValue(v); 
     return body; 
    } 

} 

身體

import javax.xml.bind.annotation.XmlAnyElement; 

public class Body { 

    private Object value; 

    @XmlAnyElement(lax=true) 
    public Object getValue() { 
     return value; 
    } 

    public void setValue(Object value) { 
     this.value = value; 
    } 

} 

CreateRq

import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlType; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "createRq") 
public class CreateRq{  
    private String id; 
    // getters and setters omitted 
} 

演示

import java.io.File; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.Unmarshaller; 

public class Demo { 

    public static void main(String[] args) throws Exception { 
     JAXBContext jc = JAXBContext.newInstance(ServiceRq.class); 
     System.out.println(jc); 

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     ServiceRq serviceRq = (ServiceRq) unmarshaller.unmarshal(new File("input.xml")); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(serviceRq, System.out); 

    } 

} 

更多信息

+0

奏效感謝。只是想補充一點,我必須將CreateRq添加到JAXBContext初始化中,以便使其工作。感謝您的幫助 – BSingh 2011-05-16 19:18:32

+0

如果我們將lax設置爲false(默認行爲),它會從xml內容創建一個dom對象,並且不會嘗試將其映射到已知對象上? – 2017-01-06 13:11:06

2

您可以使用@XmlAnyElement(lax=true)@XmlPath擴展名EclipseLink JAXB (MOXy)來處理此用例(注意:我是MOXy的負責人)。有關適用於任何JAXB實現(Metro,MOXyJaxMe等)的方法,請參閱:Jaxb complex xml unmarshall

ServiceRq

import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlAnyElement; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlType; 

import org.eclipse.persistence.oxm.annotations.XmlPath; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "serviceRq") 
public class ServiceRq{  

    @XmlPath("body/createRq") 
    @XmlAnyElement(lax=true) 
    private Object body; 
    // getters and setters omitted 
} 

CreateRq

import javax.xml.bind.annotation.XmlAccessorType; 
import javax.xml.bind.annotation.XmlAccessType; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.XmlType; 

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "createRq") 
public class CreateRq{  
    private String id; 
    // getters and setters omitted 
} 

演示

import java.io.File; 

import javax.xml.bind.JAXBContext; 
import javax.xml.bind.Marshaller; 
import javax.xml.bind.Unmarshaller; 

public class Demo { 

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

     Unmarshaller unmarshaller = jc.createUnmarshaller(); 
     ServiceRq serviceRq = (ServiceRq) unmarshaller.unmarshal(new File("input.xml")); 

     Marshaller marshaller = jc.createMarshaller(); 
     marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
     marshaller.marshal(serviceRq, System.out); 

    } 
} 

JA xb.properties

要使用MOXy作爲JAXB提供程序,您必須包含一個名爲jaxb的文件。在同一個包屬性域模型如下條目:

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

更多信息