2016-07-14 35 views
1

我想用一個類來映射我從XML請求中得到的響應。 但xml響應不同,具體取決於某些設置。例如,在一個響應中,我得到了填充所有者對象ID的標籤「owner」。如果我在我的請求中添加一個設置,我將返回完整的所有者數據,如名字和姓氏。現在我想根據響應將所有者標記映射到一個String變量或一個Class。JAXB映射1 XML標記到2個變量

例子:

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = "domain") 
public class Response { 

    @XmlElement 
    private String name; 

    @XmlElement(name = "owner") 
    private String ownerSimple; 

    @XmlElement(name = "owner") 
    private Owner ownerComplex; 

} 

@XmlRootElement(name = "ownerc") 
public class OwnerC { 

    @XmlElement 
    int id; 

    @XmlElement 
    String fname; 

    @XmlElement 
    String lname; 
} 

XML映射:

<response> 
    <name>Foo</name> 
    <owner>1234</owner> <!-- in this case it's only a id --> 
</response> 

<response> 
    <name>Foo</name> 
    <owner> <!-- in this case it's the owner class --> 
     <id>1234</id> 
     <fname>Jon</fname> 
     <lname>Doe</lname> 
    </owner> 
</response> 

回答

1

您可以使用@XmlAnyElement(lax=true)來處理這個用例。此註釋允許您將任何XML解組到Java對象(DOM Node)。在第二步驟中,有可能給Node解組到所需的對象

響應

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = "domain") 
public class Response { 

    @XmlElement 
    private String name; 

    @XmlAnyElement(lax=true) 
    private Object owner; 

    private String ownerSimple; 

    @XmlTransient 
    private Owner ownerComplex; 

所有者

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlRootElement(name = "owner") 
public class Owner { 

    @XmlElement 
    int id; 

    @XmlElement 
    String fname; 

    @XmlElement 
    String lname; 

的Unmarshaller

//Unmarshaller. Step 1 - Decodes Response and set a DOM Node at Owner 
//Important. Owner class must not be present in JAXB context, letting next step to decode the object properly. 
//Owner variable at Response class is annotated with @XmlTransient 
JAXBContext jaxbContext = JAXBContext.newInstance(Response.class); 
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); 
Response response = (Response) jaxbUnmarshaller.unmarshal(reader); 

//Unmarshaller. Step 2. Convert Node to the suitable Object 
//Considering both cases, simple-> String complex -> Owner Object.  
String ownerSimple = ((Node)response.getOwner()).getFirstChild().getNodeValue(); 
if (ownerSimple != null){ 
    response.setOwnerSimple(ownerSimple); 
} else { 
    JAXBContext jaxbContextOwner = JAXBContext.newInstance(Owner.class); 
    Unmarshaller jaxbUnmarshallerOwner = jaxbContextOwner.createUnmarshaller(); 
    Owner ownerComplex = (Owner) jaxbUnmarshallerOwner.unmarshal((Node)response.getOwner()); 
    response.setOwnerComplex(ownerComplex); 
} 

//Marshaller to system.out. Your object is well mapped in both cases 
Marshaller marshaller = jaxbContext.createMarshaller(); 
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
marshaller.marshal(rx, System.out); 
+0

嘿!這個解決方案聽起來很棒我只需要改進一件事。當我創建輸出時,是否有可能將「ownerSimple」映射到標記「所有者」,因此輸出XML看起來與輸入XML相同? – inf3ction

+1

Hi @ inf3ction。 「ownerSimple」標籤未映射。如果你使用提供的示例代碼編寫代碼,它將在「owner」標籤上寫入與兩種情況下輸入相同的內容(我已檢查過它)。爲了提供新的內容,我認爲您可以在馬歇爾時間將owner的值設置爲ownerSimple或ownerComplex,方法與unmarshalling相同。可能您需要使用Owner.class初始化'JAXBContext',具體取決於您是使用簡單還是複雜的對象 – pedrofb

+0

,非常感謝解決方案! – inf3ction