2016-07-14 10 views
1

私はXMLリクエストから得た応答をマップするのに1つのクラスを使用しようとしています。 xmlレスポンスは、いくつかの設定に応じて異なります。例えば、応答では、所有者オブジェクトのIDで満たされたタグ "owner"が得られます。私の要求に設定を追加すると、私はfirstnameとlastnameのような完全な所有者データを返すでしょう。今私は、レスポンスに応じて、所有者タグを文字列変数またはクラスのいずれかにマップしたいと思います。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

ねえ、そこに!このソリューションは素晴らしいと思います。私は1つだけ改善する必要があります。出力を作成するときに、 "ownerSimple"をタグ "owner"にマップすることができるので、出力XMLは入力XMLと同じに見えますか? – inf3ction

+1

こんにちは@ inf3ction。 「ownerSimple」タグはマップされていません。提供されたサンプルコードでマーシャルすると、どちらの場合でも(所有者のチェックをした)同じ内容の "owner"タグが入力として書き込まれます。新しいコンテンツを提供するために、マーシャリング時と同じ方法でマーシャリング時に "owner"の値をownerSimpleまたはownerComplexに設定できると思います。おそらく、単純なオブジェクトや複雑なオブジェクトを使用しているかどうかに応じて、Owner.classで 'JAXBContext'を初期化する必要があります。 – pedrofb

+0

このソリューションには感謝しています! – inf3ction

関連する問題