通过属性嵌套对象

时间:2019-03-27 06:25:16

标签: java xml jaxb

我尝试使用嵌套对象来解析xml文件,这些对象由唯一属性引用。

<items>
   <item id="firstItem" />
   <item id="secondItem">
      <dependencies>
         <dependency id="firstItem" />
      </dependencies>
   </item>
</items>

当前,我正在使用常规方式,并为每个标签创建一个新类。

@XmlRootElement(name = "items")
public class Items {
   private List<Item> items = new ArrayList();

   @XmlElement(name = "item")
   public List<Item> getItems() {
      return items;
   }
   /* setter */
}

public class Item {
   private string id;
   private Dependencies dependencies = new Dependencies();

   @XmlAttribute(name = "id")
   public String getId() {
      return id;
   }
   /* setter */

   @XmlElement(name = "dependencies")
   public Dependencies getDependencies() {
      return dependencies;
   }
   /* setter */
}

public class Dependencies {
   private List<Dependency> dependencies = new ArrayList();

   @XmlElement(name = "dependency") 
   public List<Dependency> getDependencies() {
      return dependencies;
   }
   /* setter */
}

public class Dependency {
   private String id;

   @XmlAttribute(name = "id")
   public String getId() {
      return id;
   }
   /* setter */
}

并使用javax.xml.bind.Unmarshaller读取文件

Items items = new items();
JAXBContext context = JAXBContext.newInstance(Items.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
items = (Items) unmarshaller.unmarshal(/* My InputStream */);

首选结果是单个类,该类可以保存其自身列表。

public class Item {
   private List<Item> dependencies = new ArrayList();
}

可以使用xml工具吗?

1 个答案:

答案 0 :(得分:0)

您需要编写自定义适配器,但即使您无权访问父项列表。因此,您可以在自定义适配器中反序列化ID,并在反序列化之后链接Item对象。实施示例:

import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class JaxbApp {

    public static void main(String[] args) throws Exception {
        File xmlFile = new File("./resource/test.xml").getAbsoluteFile();

        JAXBContext context = JAXBContext.newInstance(Items.class);

        Unmarshaller unmarshaller = context.createUnmarshaller();
        Items root = (Items) unmarshaller.unmarshal(xmlFile);

        System.out.println(root);
    }
}

class ItemXmlAdapter extends XmlAdapter<Object, Item> {

    @Override
    public Item unmarshal(Object v) {
        Element element = (Element) v;
        Node dependencies = element.getFirstChild();
        List<String> ids = new ArrayList<>();
        if (dependencies != null) {
            NodeList childNodes = dependencies.getChildNodes();
            for (int i = 0; i < childNodes.getLength(); i++) {
                Node item = childNodes.item(i);
                NamedNodeMap attributes = item.getAttributes();
                if (attributes != null) {
                    Node id = attributes.getNamedItem("id");
                    if (id != null) {
                        ids.add(id.getNodeValue());
                    }
                }
            }
        }

        Item item = new Item();
        item.setId(element.getAttribute("id"));
        item.setDependencyIds(ids);

        return item;
    }

    @Override
    public Object marshal(Item v) throws Exception {
        return null; // Implement if needed
    }
}

@XmlRootElement(name = "items")
class Items {

    private List<Item> items = new ArrayList<>();

    @XmlElement(name = "item")
    public List<Item> getItems() {
        return items;
    }
}

@XmlJavaTypeAdapter(ItemXmlAdapter.class)
class Item {

    private String id;
    private List<String> dependencyIds;
    private List<Item> dependencies;

    // getters, setters
}

为您的XML打印件:

Items{items=[Item{id='firstItem', dependencyIds=[]}, Item{id='secondItem', dependencyIds=[firstItem]}]}