2

JAXB を使用して、次のようないくつかのシリアル化されたオブジェクトを含む xml ドキュメントをアンマーシャリングしたいと思います。

<?xml version="1.0" encoding="UTF-8"?>
<Users>
<User>
    <firstName>first name value 1</firstName>
    <lastName>last name value 1</lastName>
    <account>
        <expiration>expire 1</expiration>
        <login>login 1</login>
    </account>
</User>
<User>
    <firstName>first name value 2</firstName>
    <lastName>last name value 2</lastName>
    <account>
        <expiration>expire 2</expiration>
        <login>login 2</login>
    </account>
</User>
...
</Users>

実際には、たとえば「Users」という名前で、User の要素のリストを含む (@XmlWrapper アノテーション付きの) 新しいクラスを作成したくありません。

xml に変換する必要がある Java オブジェクトは次のとおりです。

@Entity
@Table(name="USERS")
@XmlRootElement(name="User")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String firstName;
    private String lastName;

    @OneToOne(cascade={CascadeType.REMOVE}, mappedBy="user")
    private Account account;

    @XmlAttribute
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    @XmlElement
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @XmlElement
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @XmlInverseReference(mappedBy="user")
    @XmlElement
    public Account getAccount() {
        return account;
    }

    public void setAccount(Account account) {
        this.account = account;
    }
}

そして今のところ、1 つの xml だけを User Java オブジェクトに非整列化することができます。このような :

@Test
    public void test2() {
        try {
            JAXBContext jc = JAXBContext.newInstance(User.class);
            Unmarshaller u = jc.createUnmarshaller();

            File f = new File("user.xml");
            User element = (User) u.unmarshal(f);

            System.out.println(
                    element.getAccount().getLogin()
                    );

        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

また、User インスタンスだけでなく、User Java リスト インスタンスを取得したいと考えています。たとえば、このように:

List<User> elements = (List<User>) u.unmarshal(f);

これが可能であることを願っており、その方法を知りたいです;)


Blaise さん、お返事ありがとうございます。

私はあなたがしたように作ろうとしましたが、エラーがあります:

java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.ElementNSImpl を com.thales.momoko.ws.model.User にキャストできません

ここに私のコードのいくつかの関連部分があります:

public class Tools<T> {

public List<T> getItems(Class<T> entityClass, String xmlLocation) {
    try {
        JAXBContext jc = JAXBContext.newInstance(Wrapper.class, entityClass.getClass());
        Unmarshaller unmarshaller = jc.createUnmarshaller();

        BufferedReader br = new BufferedReader(
                new InputStreamReader(
                this.getClass().getClassLoader().getResourceAsStream(xmlLocation)));

        System.out.println(br.readLine());

        Wrapper<T> wrapper = (Wrapper<T>) unmarshaller.unmarshal(new StreamSource(br), Wrapper.class).getValue();

        System.out.println(wrapper);

        return wrapper.getItems();

    } catch (JAXBException ex) {
        Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IOException ex) {
        Logger.getLogger(Tools.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}
}

最初の println は、xml ファイルの最初の行を表示するため、正常に動作します。

<?xml version=....>

2 番目の println は、アンマーシャリングの問題を示しています。

Wrapper{items=[[ユーザー: null], [ユーザー: null], [ユーザー: null], [ユーザー: null], [ユーザー: null], [ユーザー: null], [ユーザー: null], [ユーザー: null]、[ユーザー: null]、[ユーザー: null]、[ユーザー: null]、[ユーザー: null]、[ユーザー: null]、[ユーザー: null]、[ユーザー: null]]}

ラッパー:

public class Wrapper<T> {

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

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

@Override
public String toString() {
    return "Wrapper{" + "items=" + items + '}';
}
}

そして最後にアンマーシャラーの呼び出し:

@PostConstruct
public void init() {
   this.entityClass = User.class;
    for (User user : (List<User>) new Tools<User>().getItems(User.class, "user.xml"))
        System.out.println(user.getFirstName());
}

「for」命令のある行でエラーが発生します。

このエラーについての考えはありますか?

もう一度ありがとう!

編集

解決 :

public class Tools<T> {

public static <T> List<T> getItems(Class<T> entityClass, String xmlLocation) {
    try {
        JAXBContext jc;
        synchronized (JAXBContext.class) {
            jc = JAXBContext.newInstance(Wrapper.class, entityClass);
        }

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        BufferedReader br = new BufferedReader(
                new InputStreamReader(
                Import.class.getClassLoader().getResourceAsStream(xmlLocation)));

        Wrapper<T> wrapper = (Wrapper<T>) unmarshaller.unmarshal(new StreamSource(br), Wrapper.class).getValue();

        return wrapper.getItems();

    } catch (JAXBException ex) {
        Logger.getLogger(Import.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
}
}

呼び出し :

@PostConstruct
public void init() {
   this.entityClass = User.class;
    for (User user : (List<User>) Tools.getItems(User.class, "user.xml"))
        em.persist(user);
}
4

1 に答える 1

2

JAXB を StAX で使用して、次のことを行うことができます。

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

public class Demo {

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

        XMLInputFactory xif = XMLInputFactory.newFactory();
        StreamSource xml = new StreamSource("src/forum17047306/input.xml");
        XMLStreamReader xsr = xif.createXMLStreamReader(xml);

        List<User> users = new ArrayList<User>();
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        while(xsr.getEventType() != XMLStreamReader.END_DOCUMENT) {
            if(xsr.isStartElement() && "User".equals(xsr.getLocalName())) {
                User user = (User) unmarshaller.unmarshal(xsr);
                users.add(user);
            }
            xsr.next();
        }
        System.out.println(users.size());
    }

}

アップデート

一般的なリスト ラッパー オブジェクトを使用してリストを処理するには、次の方法をお勧めします。

于 2013-06-13T16:58:22.527 に答える