Вложенные объекты через атрибут - PullRequest
0 голосов
/ 27 марта 2019

Я пытаюсь проанализировать 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 голосов
/ 30 марта 2019

Вам нужно написать собственный адаптер, но даже если у вас нет доступа к родительскому списку элементов. Таким образом, вы можете десериализовать идентификаторы в специальном адаптере и связать объекты 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]}]}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...