2017-10-31 19 views
3

要素を整列化しようとしていますが、場合によっては最終的なXMLに書き込まれないようにする必要があります。 nillable。JAXB要素を任意または両方ともマーシャリングする方法

<root> 
    <element> 
     <sub1>Whatever1</sub1> 
     <sub2 xsi:nil="true"/> 
    </element> 
    <element> 
     <sub1>Whatever2</sub1> 
     <sub2>Not empty</sub2> 
    </element> 
    <element> 
     <sub1>Whatever3</sub1> 
    </element> 
</root> 

要素「SUB2は」私はとのトラブルを抱えているものです以下の例を考えてみましょう。 、私はどうなる代わりに、最後の2を取得するには

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "element", propOrder = { 
     "sub1", 
     "sub2", 
}) 
public class Element { 

    @XmlElement(required = true) 
    public String sub1; 
    @XmlElement(nillable = true) 
    public String sub2; 
    //... 
} 

::私は簡単に次のように宣言された要素のクラスで最初の2例を達成することができます私の理解から、

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "element", propOrder = { 
     "sub1", 
     "sub2", 
}) 
public class Element { 

    @XmlElement(required = true) 
    public String sub1; 
    @XmlElement(required = false) //I could omit it entirely 
    public String sub2; 
    //... 
} 

があります両方を得る方法?

私はJava 6/JAXB 2.1.10を余儀なくされました。

ありがとうございます。

+0

あなたのpojoは、xml要素の両方の型を理解することができます。あなたは何をしていないのですか? xmlを2つの形式で "生成"するか、またはxmlを指定された形式で読み込みますか?あなたのpojoを使用すると、提供されたxmlを正しくアンマーシャルすることができます – Optional

答えて

2

はい、必須ではない要素と不可能な要素を持つことは可能です。あなたはこの仕事をするために行う必要があるいくつかのものがあります。

  1. フィールドJAXBElement<String>の代わりStringください。
  2. ObjectFactoryクラスをファクトリメソッドで作成します。
  3. @XmlElementDeclObjectFactoryおよび@XmlElementRefの工場出荷時のメソッドのElementフィールドに入力します。

例:

@XmlElementRefアノテーションでフィールドJAXBElement<String>を行います

@XmlAccessorType(XmlAccessType.FIELD) 
@XmlType(name = "element", propOrder = {"sub1", "sub2"}) 
@XmlRootElement 
public class Element { 

    @XmlElement(required = true) 
    public String sub1; 

    @XmlElementRef(name = "sub2", required = false) 
    public JAXBElement<String> sub2; 

    // ... 
} 

@XmlElementDeclアノテーションで、ファクトリメソッドでObjectFactoryクラスを作成します。

@XmlRegistry 
public class ObjectFactory { 

    @XmlElementDecl(name = "sub2") 
    public JAXBElement<String> createSub2(String value) { 
     return new JAXBElement<>(new QName(null, "sub2"), 
           String.class, Element.class, value); 
    } 
} 

は、例1マーシャリング:

ObjectFactory objectFactory = new ObjectFactory(); 

Element element = new Element(); 
element.setSub1("one"); 
element.setSub2(objectFactory.createSub2("two")); 

JAXBContext context = JAXBContext.newInstance(ObjectFactory.class, Element.class); 

Marshaller marshaller = context.createMarshaller(); 
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); 
marshaller.marshal(element, System.out); 

出力:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<element> 
    <sub1>one</sub1> 
    <sub2>two</sub2> 
</element> 

マーシャリングsub2の値を持って@XmlElementRef@XmlElementDecl注釈の名前空間と名前が同じであることに注意してください例2:XMLの要素がまったくありません。

Element element = new Element(); 
element.setSub1("one"); 
// Leave the field sub2 set to null 

出力:

Element element = new Element(); 
element.setSub1("one"); 
element.setSub2(objectFactory.createSub2(null)); 

出力:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<element> 
    <sub1>one</sub1> 
    <sub2 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/> 
</element> 
nilに設定されているXML要素として表示される値 null持つ要素を作成する:例3をマーシャリング

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<element> 
    <sub1>one</sub1> 
</element> 

+0

これは、Java 7およびJAXB 2.2以上に最適な答えです。しかし残念ながら私はJava 6/JAXB 2.1.10を余儀なくされています。私はそれもJava 6でも動作させようとしています...ここでいくつかの変更を加えることが可能かどうかをお知らせします。 – Nevril

+1

Java 6とJAXB 2.1にはいくつかの変更が必要でしたが、全体的には正しかったし、うまく機能しました。特に、XmlElementRefアノテーションは '@XmlElementRef(name =" sub2 "、type = JAXBElement.class)'に変更する必要がありました。 ObjectFactory内のXmlElementDeclを '@XmlElementDecl(name =" sub2 "、scope = Element.class)'と返された値の型として 'return new JAXBElement (...)'と明示的に記述します。あなたの答えをありがとう。 – Nevril

関連する問題