9

XML解析を使用して以下をSimpleXML解析しようとしています。
を解析するためにさまざまな方法を試しましAttributesElementが、以下の XML の解析に成功しませんでした。
下部にリストされているエラーが生成されます。

<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
  <order>
    <id>1</id>
    <id_address_delivery xlink:href="http://abc.com/add/1">1</id_address_delivery>
    <id_address_invoice xlink:href="http://abc.com/add/2">2</id_address_invoice>
  </order>
</prestashop>

Order.java

@Root(name="order")
@Namespace(reference="http://www.w3.org/1999/xlink",prefix="xlink")
public class Order {

    @Element(name="id",required=true)
    private int order_id;

    @Element(name="id_address_delivery",required=false)
    private int id_address_delivery;
    @Attribute( name="href", required=false)
    private String id_address_delivery_href;


    @Element(name="id_address_invoice",required=false)
    private int id_address_invoice;
    @Attribute(name="href", required=false)
    private String id_address_invoice_href;
}

OrderObject.java

public class OrderObject
{
    @ElementList(required=true, inline=true)
    private List<Order> list = new ArrayList<Order>();

    public List<Order>getList()
    {
        return this.list;
    }
}

私が得る例外は次のとおりです。

WARN/System.err(988): org.simpleframework.xml.core.PersistenceException: 
Duplicate annotation of name 'href' on field 'id_address_delivery_href' 
private java.lang.String com.prestashop.orders.Order.id_address_delivery_href
at org.simpleframework.xml.core.StructureBuilder.process(StructureBuilder.java:250)
at org.simpleframework.xml.core.StructureBuilder.process(StructureBuilder.java:173)
at org.simpleframework.xml.core.ObjectScanner.field(ObjectScanner.java:438)
at org.simpleframework.xml.core.ObjectScanner.scan(ObjectScanner.java:371)
at org.simpleframework.xml.core.ObjectScanner.<init>(ObjectScanner.java:82)
.
.
4

1 に答える 1

9

この例外の理由は、両方の@Attribute注釈です。次の要素ではなく、Orderオブジェクト全体に設定されます。注釈はhref2 回設定されますが、値が異なります。

の JavaDoc を参照してください@Attribute:

Attribute注釈は、XML 要素内のシリアライズ可能な XML 属性を表します。[...]

しかし、素晴らしくシンプルな解決策があります。要素と属性を組み合わせる代わりに、これを行うクラスを作成します。

OrderObjectクラス:

@Root(name = "prestashop")
@Namespace(reference = "http://www.w3.org/1999/xlink", prefix = "xlink")
public class OrderObject
{
    @ElementList(required = true, inline = true)
    private List<Order> list;


    public OrderObject()
    {
        this.list = new ArrayList<>();
    }


    public List<Order> getList()
    {
        return list;
    }


    // ...

    @Override
    public String toString()
    {
        return "OrderObject{" + "list=" + list + '}';
    }

}

注:toString()これらのクラスのメソッドは、結果を確認するためだけに実装されています!

Orderクラス:

@Root(name = "order")
public class Order
{
    @Element(name = "id")
    private int id;
    @Element(name = "id_address_delivery")
    private AdressDelivery delivery;
    @Element(name = "id_address_invoice")
    private AdressInvoice invoice;


    public Order(int id, AdressDelivery delivery, AdressInvoice invoice)
    {
        this.id = id;
        this.delivery = delivery;
        this.invoice = invoice;
    }

    private Order() {  }


    // Getter / Setter etc.


    @Override
    public String toString()
    {
        return "Order{" + "id=" + id + ", delivery=" + delivery + ", invoice=" + invoice + '}';
    }


    @Root()
    public static class AdressDelivery
    {
        @Namespace(reference = "http://www.w3.org/1999/xlink", prefix = "xlink")
        @Attribute(name = "href", required = false)
        private String link;
        @Text()
        private int value;


        public AdressDelivery(String link, int value)
        {
            this.link = link;
            this.value = value;
        }

        AdressDelivery() { }



        // Getter / Setter etc.

        @Override
        public String toString()
        {
            return "AdressDelivery{" + "link=" + link + ", value=" + value + '}';
        }
    }

    @Root()
    public static class AdressInvoice
    {
        @Attribute(name = "href", required = false)
        @Namespace(reference = "http://www.w3.org/1999/xlink", prefix = "xlink")
        private String link;
        @Text()
        private int value;


        public AdressInvoice(String link, int value)
        {
            this.link = link;
            this.value = value;
        }

        AdressInvoice() { }


        // Getter / Setter etc.

        @Override
        public String toString()
        {
            return "AdressInvoice{" + "link=" + link + ", value=" + value + '}';
        }
    }

}

属性と要素を組み合わせたAdressDeliveryおよびクラスが表示されます。AdressInvoiceそれらを内部クラスとして実装する必要はありません。それらを「通常の」ものとして自由に書いてください。また、それらを公開する必要はありません。非公開にすることも可能です (たとえば、Orderのコンストラクター内で構築します)。

Orderただし、クラス内の引数のない空のコンストラクター (および内部クラス) に注意してください。それらは必須です。しかし、それらはすべて作成できますprivate- それらを公開する必要はありません。引数のないコンストラクターを使用することだけが重要です。

使い方(例)

File f = new File("whatever.xml");

Serializer ser = new Persister();
OrderObject orderObject = ser.read(OrderObject.class, f);

System.out.println(orderObject);

このコードは、ファイルから Xml を解析し、逆シリアル化されたオブジェクトを出力します。

入力 Xml (質問のように) :

<prestashop xmlns:xlink="http://www.w3.org/1999/xlink">
  <order>
    <id>1</id>
    <id_address_delivery xlink:href="http://abc.com/add/1">1</id_address_delivery>
    <id_address_invoice xlink:href="http://abc.com/add/2">2</id_address_invoice>
  </order>
</prestashop>

結果(からprintln()) :

OrderObject{list=[Order{id=1, delivery=AdressDelivery{link=http://abc.com/add/1, value=1}, invoice=AdressInvoice{link=http://abc.com/add/2, value=2}}]}

明確に表現されていませんが、結果を見るには十分です:-)

于 2013-06-20T17:53:49.887 に答える