2

Simple Framework を使用して xml をオブジェクトに解析しています。問題は、xml に同じ名前の要素があり、パスが異なることです。

XML:

<prestashop>
 <products>
   <product>
    <name>
       <language id="1"> name </language>
    </name>
    <description>
      <language id="1"> description </language>
    </description>
    <description_short>
      <language id="1"> desc </language>
    </description_short>
  </product>
 </products>
</prestashop>

私のクラスは次のようにマッピングされます:

@Root(name="prestashop")
public class Product{
    @Element(name="language")
    @Path("products/product/description_short[1]")
    private String shortDesc;

    @Element(name="language")
    @Path("products/product/description[1]")
    private String longDesc;

    @Element(name="language")
    @Path("products/product/name[1]")
    private String name;
}

しかし、逆シリアル化中に例外が発生します。

  org.simpleframework.xml.core.PersistenceException: 
Element 'language' is already used with @org.simpleframework.xml.Element(data=false, name=language, required=true, type=void) 
on field 'name' private java.lang.String model.Product.name at line 8

同じ名前のタグを別のパスにマップするにはどうすればよいですか?

製品オブジェクトをシリアル化すると、正しい XML 構造が得られます。

<prestashop xmlns="http://www.w3.org/1999/xlink">
    <products>
       <product>
          <description_short>
             <language>short</language>
          </description_short>
          <id_default_image href="path"/>
          <description>
             <language>long</language>
          </description>
          <name>
             <language>aaa</language>
          </name>
          <price>10.0</price>
          <id>1</id>
       </product>
    </products>
 </prestashop>

私はこのように逆シリアル化しています:

product = new Product();
InputStream in = res.getResponse();
Serializer serializer = new Persister();
serializer.read(product, in,false);
4

1 に答える 1

3

クラスをマップする方法の例を次に示します。

(例-) クラス:

@Root(name = "product")
public class Product
{
    @Path(value = "name")
    @Element(name = "language")
    private String name;

    @Path(value = "description")
    @Element(name = "language")
    private String description;

    @Path(value = "description_short")
    @Element(name = "language")
    private String desc;


    // ...

    /* For testing only */
    @Override
    public String toString()
    {
        return "Product{" + "name=" + name + ", description=" + description + ", desc=" + desc + '}';
    }
}

(完全な実装はありませんが、私の例が似ていることを願っています)

入力 XML:

<product>
    <name>
        <language id="1"> name </language>
    </name>
    <description>
        <language id="1"> description </language>
    </description>
    <description_short>
        <language id="1"> desc </language>
    </description_short>
</product>

<product> </product>タグと"for属性に注意してくださいid(それらがないと失敗する可能性があります)。

テストコード:

final File f = new File("test.xml"); // Input file

Serializer ser = new Persister();
Product p = ser.read(Product.class, f); // deserialize the class


System.out.println(p); // output - thats why i've implemented the 'toString()' method

出力:

Product{name= name , description= description , desc= desc }

(空白はxmlが原因)

リストをシリアライズ/デシリアライズしたいように見えるのでproducts、リスト(インライン化可能)である必要があり、product上記のクラスです。



編集:

Productクラス:

@Root(name = "product")
public class Product
{
    @Path(value = "name")
    @Element(name = "language")
    private String name;

    @Path(value = "description")
    @Element(name = "language")
    private String description;

    @Path(value = "description_short")
    @Element(name = "language")
    private String desc;

    @Element(name = "id_default_image")
    private AttributedElement idDefaultImage;

    @Element(name = "price")
    private double price;

    @Element(name = "id")
    private int id;



    @Override
    public String toString()
    {
        return "Product{" + "name=" + name + ", description=" + description 
                + ", desc=" + desc + ", idDefaultImage=" + idDefaultImage 
                + ", price=" + price + ", id=" + id + '}';
    }



    @Root(name = "AttributedElement")
    static class AttributedElement
    {
        @Attribute(name = "href")
        private String value;


        public AttributedElement(String value)
        {
            this.value = value;
        }

        private AttributedElement()
        {
            /* Empty constructor required here */
        }


        @Override
        public String toString()
        {
            return value;
        }
    }

}

注:その内部クラスをヘルパーとして使用して、画像要素の適切な xml 構造を取得しました。

さて、次に . をラップするクラスがありProductます。私はこれをマップとして実装しましたが、製品が 1 つしかない場合は、リストの代わりに単純なクラスを使用できます。

Prestashopクラス:

@Root(name = "prestashop")
public class Prestashop
{
    @ElementList(name = "products", empty = false, required = true)
    private ArrayList<Product> products;


    public Prestashop()
    {
        this.products = new ArrayList<>();
    }


    /* Some list methods */

    public void add(Product p)
    {
        products.add(p);
    }

    public Product get(int index)
    {
        return products.get(index);
    }

    public Product first()
    {
        return products.get(0);
    }

}

注:ここで使用しない理由については、この回答List<Product>を参照してください。

テストコード:

Serializer ser = new Persister();

Prestashop shop = ser.read(Prestashop.class, f);
System.out.println(shop.first());

入力 XML:

<prestashop xmlns="http://www.w3.org/1999/xlink">
    <products>
       <product>
          <description_short>
             <language>short</language>
          </description_short>
          <id_default_image href="path"/>
          <description>
             <language>long</language>
          </description>
          <name>
             <language>aaa</language>
          </name>
          <price>10.0</price>
          <id>1</id>
       </product>
    </products>
 </prestashop>

(あなたの質問の2番目のもの)

そして最後 ...

出力:

Product{name=aaa, description=long, desc=short, idDefaultImage=path, price=10.0, id=1}
于 2013-05-07T14:37:45.963 に答える