2 votes

XStream analyse XML avec des balises en double

Je possède une structure XML comme ci-dessous :

      One

      Two

      1

      2

J'essaie de l'analyser en utilisant XStream, avec les classes suivantes :

@XStreamAlias("Groups")
class GroupData {
  List Products;
  List OtherProducts;
}

@XStreamAlias("Product")
class Product {
   String name;
}

@XStreamAlias("Product")
class OtherProduct {
   int id;
}

Et c'est là que le problème se trouve -- le parseur essaie de convertir les éléments "Product" en utilisant la classe "OtherProduct".

Je crois qu'il doit y avoir un moyen de spécifier la classe à utiliser pour analyser un objet XML, mais je ne comprends pas les attributs XStream.

Toute aide serait grandement appréciée.

2voto

pablosaraiva Points 1128

La solution n'est pas évidente.

Le marshal (d'objet à XML) est assez simple, le problème survient lors du unmarshal (XML à objet).

Le problème est que lorsque XStream commence à lire le XML et qu'il trouve une balise Product, il ne peut pas savoir avec certitude s'il s'agit d'un objet "Product" ou "OtherProduct", car le nom de la balise est le même.

Vous devez donc apprendre à XStream à regarder en avant et vérifier quelque chose que vous savez qui les différencie. Dans ce cas, les attributs internes "Name" et "Id".

Vous pouvez enseigner à XStream comment faire cela en écrivant des Converters.

La solution ci-dessus montre comment résoudre le problème.

Classe Product:

@XStreamAlias("Product")
public class Product {

    @XStreamAlias("Name")
    private String name;

    public Product() {
    }

    public Product(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    }

}

Classe OtherProduct:

@XStreamAlias("Product")
public class OtherProduct {

    @XStreamAlias("Id")
    private int id;

    public OtherProduct() {

    }

    public OtherProduct(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

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

}

Classe GroupData:

@XStreamAlias("Groups")
public class GroupData {
    @XStreamAlias("Products")
    private List products = new ArrayList<>();

    @XStreamAlias("OtherProducts")
    private List otherProducts = new ArrayList<>();

    public void add(Product product) {
        getProducts().add(product);
    }

    public void add(OtherProduct otherProduct) {
        getOtherProducts().add(otherProduct);
    }

    public List getProducts() {
        return products;
    }

    public List getOtherProducts() {
        return otherProducts;
    }

}

Classe ProductConverter:

public class ProductConverter implements Converter {
    private ProductUnmarshaller productUnmarshaller = new ProductUnmarshaller();

    @Override
    public boolean canConvert(@SuppressWarnings("rawtypes") Class clazz) {
        return clazz.equals(Product.class);
    }

    @Override
    public void marshal(Object object, HierarchicalStreamWriter hsw, MarshallingContext mc) {
        Product product = (Product) object;
        hsw.startNode("Name");
        hsw.setValue(product.getName());
        hsw.endNode();
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader hsr, UnmarshallingContext uc) {
        return productUnmarshaller.unmarshal(hsr, uc);
    }

}

Classe OtherProductConverter:

public class OtherProductConverter implements Converter {
    private ProductUnmarshaller productUnmarshaller = new ProductUnmarshaller();

    @Override
    public boolean canConvert(@SuppressWarnings("rawtypes") Class clazz) {
        return clazz.equals(OtherProduct.class);
    }

    @Override
    public void marshal(Object object, HierarchicalStreamWriter hsw, MarshallingContext mc) {
        OtherProduct otherProduct = (OtherProduct) object;
        hsw.startNode("Id");
        hsw.setValue(Integer.toString(otherProduct.getId()));
        hsw.endNode();
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader hsr, UnmarshallingContext uc) {
        return productUnmarshaller.unmarshal(hsr, uc);
    }

}

Classe ProductUnmarshaller:

public class ProductUnmarshaller {

    public Object unmarshal(HierarchicalStreamReader hsr, UnmarshallingContext uc) {
        hsr.moveDown();

        String nodeName = hsr.getNodeName();
        String nodeValue = hsr.getValue();

        hsr.moveUp();

        if ("Name".equals(nodeName)) {
            return new Product(nodeValue);
        } else if ("Id".equals(nodeName)) {
            return new OtherProduct(Integer.parseInt(nodeValue));
        } else {
            return null;
        }

    }

}

Et enfin, une classe utilisant tout cela:

public class ProductTest {
    @Test
    public void test() {
        Product productOne = new Product("One");
        Product productTwo = new Product("Two");

        OtherProduct otherProduct1 = new OtherProduct(1);
        OtherProduct otherProduct2 = new OtherProduct(2);

        GroupData group = new GroupData();
        group.add(productOne);
        group.add(productTwo);
        group.add(otherProduct1);
        group.add(otherProduct2);

        XStream xs = new XStream();
        xs.processAnnotations(GroupData.class);
        xs.processAnnotations(OtherProduct.class);
        xs.processAnnotations(Product.class);
        xs.registerConverter(new ProductConverter());
        xs.registerConverter(new OtherProductConverter());
        String xml = xs.toXML(group);
        System.out.println(xml);
        GroupData gd = (GroupData) xs.fromXML(xml);

        for (Product product: gd.getProducts()) {
            System.out.println(product.getName());
        }

        for (OtherProduct otherProduct: gd.getOtherProducts()) {
            System.out.println(otherProduct.getId());
        }

    }

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X