11

インターネットで JAXB2 の例をいくつか見つけましたが、 with@XmlRegistryを使用する概念について説明している詳細なチュートリアルはありません。@XmlRegistry@XmlElementDecl

とにかく、ここに私の質問があります。まず、JAXB を使用して xml を非整列化するために使用しているいくつかのサンプル クラスです。

JAXB を使用して非整列化しようとしているメイン クラス - Employee.java

package com.test.jaxb;

import java.util.List;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;

import com.test.jaxb.dto.Address;

@XmlRootElement
public class Employee {
    private int id;
    private String name;
    private String email;

    private List<Address> addresses;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }

    public List<Address> getAddresses() {
        return addresses;
    }
    public void setAddresses(List<Address> addresses) {
        this.addresses = addresses;
    }

    @SuppressWarnings("unused")
    @XmlRegistry
    public static class XMLObjectFactory {
        @XmlElementDecl(scope = Employee.class, name= "id")
        JAXBElement<String> createEmployeeId(String value) {
            return new JAXBElement<String>(new QName("id"), String.class, "100");
        }
        @XmlElementDecl(scope = Employee.class, name= "name")
        JAXBElement<String> createName(String value) {
            return new JAXBElement<String>(new QName("name"), String.class, "Fake Name");
        }
        @XmlElementDecl(scope = Employee.class, name= "email")
        JAXBElement<String> createEmail(String value) {
            return new JAXBElement<String>(new QName("email"), String.class, value);
        }

        @XmlElementDecl(scope = Employee.class, name= "addresses")
        JAXBElement<List> createAddresses(List value) {
            return new JAXBElement<List>(new QName("addresses"), List.class, value);
        }
    }
}

子クラス - Address.java

package com.test.jaxb.dto;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;

import com.test.jaxb.Employee;

@XmlRootElement
public class Address {
    private String addressLine1;
    private String addressLine2;
    private String addressLine3;
    public String getAddressLine1() {
        return addressLine1;
    }
    public void setAddressLine1(String addressLine1) {
        this.addressLine1 = addressLine1;
    }
    public String getAddressLine2() {
        return addressLine2;
    }
    public void setAddressLine2(String addressLine2) {
        this.addressLine2 = addressLine2;
    }
    public String getAddressLine3() {
        return addressLine3;
    }
    public void setAddressLine3(String addressLine3) {
        this.addressLine3 = addressLine3;
    }

    @SuppressWarnings("unused")
    @XmlRegistry
    private static class XMLObjectFactory {
        @XmlElementDecl(scope = Employee.class, name= "addressLine1")
        JAXBElement<String> createAddressLine1(String value) {
            return new JAXBElement<String>(new QName("addressLine1"), String.class, value);
        }
        @XmlElementDecl(scope = Employee.class, name= "addressLine2")
        JAXBElement<String> createAddressLine2(String value) {
            return new JAXBElement<String>(new QName("addressLine2"), String.class, value);
        }
        @XmlElementDecl(scope = Employee.class, name= "addressLine3")
        JAXBElement<String> createAddressLine3(String value) {
            return new JAXBElement<String>(new QName("addressLine3"), String.class, value);
        }
    }
}

非整列化する xml - employee.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee>
    <id>1</id>
    <name>Vaishali</name>
    <email>Vaishali@example.com</email>
    <addresses>
        <address>
            <addressLine1>300</addressLine1>
            <addressLine2>Mumbai</addressLine2>
            <addressLine3>India</addressLine3>
        </address>
        <address>
            <addressLine1>301</addressLine1>
            <addressLine2>Pune</addressLine2>
            <addressLine3>India</addressLine3>
        </address>
    </addresses>
</employee>

アンマーシャリングコード:

package com.test.jaxb;

import java.io.FileReader;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;


public class ObjectFactoryTest {
    public static void main(String[] args) throws Exception {
        FileReader reader = new FileReader("resources/employee.xml");
        JAXBContext context = JAXBContext.newInstance(Employee.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        Object obj = unmarshaller.unmarshal(reader);
        System.out.println(obj);
    }
}

上記のコードを使用して従業員 xml をアンマーシャリングすると、アドレス リストにデータが入力されません。結果の従業員オブジェクトには、住所の空のリストしかありません。マッピングに何か問題がありますか?

何が起こっているのかを調べ、(@XMLRegistry アノテーションを持つ) オブジェクト ファクトリを使用して従業員オブジェクトが実際に作成されているかどうかを確認するために、ファクトリ メソッドの id と name の値を変更しましたが、出力には影響しませんでした。これは、JAXB が ObjectFactory を実際に使用していないことを示しています。なぜですか?

私はこれについてすべて間違っていますか?どんな助けでも大歓迎です。

4

2 に答える 2

17

@XmlRegistry-どのように機能しますか?

@XmlRegistry@XmlElementDecl注釈を持つクラスをマークするために使用されます。JAXB実装でこのクラスを処理するには、ブートストラップに使用されるクラスのリストにこのクラスが含まれていることを確認する必要がありますJAXBContext。ドメインモデルクラスの1つの静的内部クラスであるだけでは不十分です。

JAXBContext context = JAXBContext.newInstance(Employee.class, Employee.XMLObjectFactory.class);

@XmlElementDecl-どのように機能しますか?

フィールド/プロパティの値がaになる場合は、JAXBElementを活用する必要があります@XmlElementDeclJAXBElement有用な情報をキャプチャします。

  • 要素名。これは、複数の要素が同じタイプである選択構造にマッピングする場合に必要です。要素名が一意のタイプに対応していない場合、ドキュメントをラウンドトリップすることはできません。
  • JAXBElementで要素を表すために使用できますxsi:nil="true"

XmlObjectFactory

@XmlElementDeclスコープを指定することもできます。私はあなたの投稿からモデルを少し変更しました。XmlObjectFactory2つのクラスを導入しました@XmlElementDecl。どちらもの名前を指定しますaddress。このプロパティを活用して、クラスscope内のプロパティに対応するクラスが使用されるようにしました。 Employee@XmlElementDeclAddress

package forum11078850;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;

@XmlRegistry
public class XmlObjectFactory {

    @XmlElementDecl(scope = Employee.class, name = "address")
    JAXBElement<Address> createAddress(Address value) {
        return new JAXBElement<Address>(new QName("address"), Address.class, value);
    }

    @XmlElementDecl(name = "address")
    JAXBElement<String> createStringAddress(String value) {
        return new JAXBElement<String>(new QName("address"), String.class, value);
    }

}

従業員

@XmlElementRefアノテーションにより、プロパティの値がルート要素名と一致します。一致する可能性があるのは、@XmlRootElementまたはでマップされたクラス@XmlElementDeclです。

package forum11078850;

import java.util.List;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlType(propOrder = { "id", "name", "email", "addresses" })
public class Employee {
    private int id;
    private String name;
    private String email;

    private List<JAXBElement<Address>> addresses;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @XmlElementWrapper
     @XmlElementRef(name="address")
    public List<JAXBElement<Address>> getAddresses() {
        return addresses;
    }

    public void setAddresses(List<JAXBElement<Address>> addresses) {
        this.addresses = addresses;
    }

}

ObjectFactoryTest

package forum11078850;

import java.io.FileReader;
import javax.xml.bind.*;

public class ObjectFactoryTest {
    public static void main(String[] args) throws Exception {
        FileReader reader = new FileReader("src/forum11078850/input.xml");
        JAXBContext context = JAXBContext.newInstance(Employee.class, XmlObjectFactory.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        Object obj = unmarshaller.unmarshal(reader);

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

Addressクラスと私のinput.xml元の回答から、この例を実行するために使用できます。


元の回答

あなたがどのように使用しようとしているのかわからない@XmlRegistryので、私はあなたの投稿の次の部分に焦点を当てます:

上記のコードを使用してemployeexmlをアンマーシャリングすると、アドレスリストにデータが入力されません。結果のemployeeオブジェクトには、アドレスの空白のリストしかありません。マッピングに何か問題がありますか?

オブジェクトのリストはAddressグループ化要素()でラップされているため、このユースケースをマッピングするにはアノテーションをaddresses使用する必要があります。@XmlElementWrapper以下は完全な例です。

従業員

package forum11078850;

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

@XmlRootElement
@XmlType(propOrder = { "id", "name", "email", "addresses" })
public class Employee {
    private int id;
    private String name;
    private String email;

    private List<Address> addresses;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @XmlElementWrapper
    @XmlElement(name = "address")
    public List<Address> getAddresses() {
        return addresses;
    }

    public void setAddresses(List<Address> addresses) {
        this.addresses = addresses;
    }

}

住所

package forum11078850;

public class Address {
    private String addressLine1;
    private String addressLine2;
    private String addressLine3;

    public String getAddressLine1() {
        return addressLine1;
    }

    public void setAddressLine1(String addressLine1) {
        this.addressLine1 = addressLine1;
    }

    public String getAddressLine2() {
        return addressLine2;
    }

    public void setAddressLine2(String addressLine2) {
        this.addressLine2 = addressLine2;
    }

    public String getAddressLine3() {
        return addressLine3;
    }

    public void setAddressLine3(String addressLine3) {
        this.addressLine3 = addressLine3;
    }

}

ObjectFactoryTest

package forum11078850;

import java.io.FileReader;
import javax.xml.bind.*;

public class ObjectFactoryTest {
    public static void main(String[] args) throws Exception {
        FileReader reader = new FileReader("src/forum11078850/input.xml");
        JAXBContext context = JAXBContext.newInstance(Employee.class);
        Unmarshaller unmarshaller = context.createUnmarshaller();
        Object obj = unmarshaller.unmarshal(reader);

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

input.xml / Output

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee>
    <id>1</id>
    <name>Vaishali</name>
    <email>Vaishali@example.com</email>
    <addresses>
        <address>
            <addressLine1>300</addressLine1>
            <addressLine2>Mumbai</addressLine2>
            <addressLine3>India</addressLine3>
        </address>
        <address>
            <addressLine1>301</addressLine1>
            <addressLine2>Pune</addressLine2>
            <addressLine3>India</addressLine3>
        </address>
    </addresses>
</employee>
于 2012-06-18T13:24:01.380 に答える
-1

Address の List オブジェクトを取得する必要があります。そのオブジェクトに、addressline1 のようなデータを含むオブジェクトを追加する必要があります。addressline2 など。

 i.e.
 List addrObjList = new List();
 addrObjList.add(object); // Bind an object containing data and add one by one 
于 2012-06-18T08:44:52.080 に答える