19

2 つの JavaBeansPersonとがあるとしAddressます。

Person オブジェクトのリストを作成する場合、次のようにマーシャリングしたいと思います。

<persons>
  <person>...</person>
</persons>

ここで説明されている手法を使用することができます: Using JAXB to unmarshal/marshal a List<String>

JaxbList に@XmlRootElement(name = "persons")and@XmlElement(name = "person")のアノテーションを付けることで、上記の XML にマーシャリングできます。

しかし、同じクラスを再利用してオブジェクトJaxbList<T>のリストをマーシャリングできると便利です。Address実際には、他にも多くの種類の豆があります。私は次のようなもので行くことができます:

<list>
   <item xsi:type="person" xmlns:xsi="http://www.w2.org/2001/XmlSchema-instance"></item>
</list>

しかし、理想的には、"list" をクラス名の複数形に、"item" をクラス名に置き換えるとよいでしょう。

それで、実行時に JaxbContext などをプログラムで構成し、本質的にname内部@XmlRootElementの値を設定することは可能@XmlElementですか?

または、JaxbListBean タイプごとに個別の実装を作成することなく、これを機能させる他の方法はありますか? 多分 XmlJavaTypeAdapter はこの種のことを達成できますか?

以下で承認された@Blaise Doughanのソリューションを更新すると、うまく機能します。私のユース ケースでは、Java オブジェクトから XML に直接移行する必要がありました。これが機能したものです (これは私の完全な実装ではなく、デモンストレーション用の単なる擬似コードであることに注意してください)。

    //JAXBContext is thread safe and so create it in constructor or 
    //setter or wherever:
    ... 
    JAXBContext jc = JAXBContext.newInstance(Wrapper.class, clazz);
    ... 

    public String marshal(List<T> things, Class clazz) {

      //configure JAXB and marshaller     
      Marshaller m = jc.createMarshaller();
      m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

      //Create wrapper based on generic list of objects
      Wrapper<T> wrapper = new Wrapper<T>(things);
      JAXBElement<Wrapper> wrapperJAXBElement = new JAXBElement<Wrapper>(new QName(clazz.getSimpleName().toLowerCase()+"s"), Wrapper.class, wrapper);

      StringWriter result = new StringWriter();
      //marshal!
      m.marshal(wrapperJAXBElement, result);

      return result.toString();

    }
4

1 に答える 1

18

次のような汎用Wrapperオブジェクトを作成できます。

ラッパー

Listで注釈が付けられたプロパティを持つ汎用ラッパー クラスを作成できます@XmlAnyElement(lax=true)。このリストに入力するために使用されるオブジェクトのタイプは、そのルート要素に基づきます (参照: http://blog.bdoughan.com/2010/08/using-xmlanyelement-to-build-generic.html )。

package forum13272288;

import java.util.*;
import javax.xml.bind.annotation.XmlAnyElement;

public class Wrapper<T> {

    private List<T> items = new ArrayList<T>();

    @XmlAnyElement(lax=true)
    public List<T> getItems() {
        return items;
    }

}

住所

リストの可能な内容に で注釈を付ける必要があります@XmlRootElement

package forum13272288;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Address {

}

package forum13272288;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Person {

}

デモ

以下のデモ コードは、Wrapperクラスの使用方法を示しています。ルート要素が異なる可能性があるため、ラッパー クラスに非整列化することを指定する必要があります。または、アノテーションを利用して、@XmlElementDecl複数のルート要素をラッパー クラスに関連付けることもできます ( http://blog.bdoughan.com/2012/07/jaxb-and-root-elements.htmlを参照)。

package forum13272288;

import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Wrapper.class, Person.class, Address.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        StreamSource personsXML = new StreamSource("src/forum13272288/persons.xml");
        JAXBElement<Wrapper> wrapper1 = unmarshaller.unmarshal(personsXML, Wrapper.class);
        marshaller.marshal(wrapper1, System.out);

        StreamSource addressesXML = new StreamSource("src/forum13272288/addresses.xml");
        JAXBElement<Wrapper> wrapper2 = unmarshaller.unmarshal(addressesXML, Wrapper.class);
        marshaller.marshal(wrapper2, System.out);
    }

}

出力

以下は、デモ コードを実行した結果の出力です。ファイルはpersons.xmladdresses.xml対応する出力のように見えます。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persons>
    <person/>
    <person/>
</persons>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addresses>
    <address/>
    <address/>
</addresses>

詳細については

于 2012-11-07T15:40:03.603 に答える