2

我的 XML 结构如下:

<Groups>
  <Products>
    <Product>
      <Name>One</Name>
    </Product>
    <Product>
      <Name>Two</Name>
    </Product>
  </Products>
  <OtherProducts>
    <Product>
      <Id>1</Id>
    </Product>
    <Product>
      <Id>2</Id>
    </Product>
  </OtherProducts>
</Groups>

我正在尝试使用 XStream 解析它,具有以下类:

@XStreamAlias("Groups")
class GroupData {
  List<Product> Products;
  List<OtherProduct> OtherProducts;
}

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

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

这就是问题所在——解析器尝试使用“OtherProduct”类转换“Product”项。

我相信必须有某种方法来指定用于解析 XML 对象的类,但我无法确定 XStream 属性的正面或反面。

任何帮助将不胜感激。

4

1 回答 1

2

解决方案并不简单。

编组(对象到 XML)非常简单,当您必须解组(XML 到对象)时问题就来了。

发生的情况是,当 XStream 开始读取 XML 并找到 Product 标签时,它无法确定它是“Product”还是“OtherProduct”对象,因为标签名称相同。

因此,您必须教 XStream 向前看,并检查您所知道的使它们与众不同的东西。在这种情况下,内部属性“Name”和“Id”。

您可以教 XSTream 如何编写转换器。

上面的解决方案显示了如何解决问题。

产品类别:

@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;

    }

}

其他产品类别:

@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;
    }

}

组数据类:

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

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

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

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

    public List<Product> getProducts() {
        return products;
    }

    public List<OtherProduct> getOtherProducts() {
        return otherProducts;
    }

}

产品转换器类:

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);
    }

}

其他产品转换器类:

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);
    }


}

ProductUnmarsheller 类:

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;
        }



    }

}

最后,一个使用它的类:

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());
        }

    }

}
于 2013-09-13T15:57:44.587 回答