【问题标题】:Can not populate List<Item> from XML nodes无法从 XML 节点填充 List<Item>
【发布时间】:2015-11-23 08:01:59
【问题描述】:

我有一个要解析的 xml 文档,其中包含我尝试过的嵌套节点,但无法按要求完成工作。 XML 文档是

<Items>
   <Item>
   <MediumImage>
      <URL>http://ecx.images-amazon.com/images/I/51l7DDD1qNL._SL160_.jpg</URL>
      <Height Units="pixels">160</Height>
      <Width Units="pixels">160</Width>
   </MediumImage>
   <Title>Fallout 4 Vault Dweller's Survival Guide Collector's Edition: Prima Official Game Guide</Title>
   <OfferSummary>
   <LowestNewPrice>
   <Amount>1952</Amount>
   </OfferSummary>
   </Item>
   .
   .
   .
</Items>

我已经将 Title 节点值获取为

private static NodeList fetchTitle(String requestUrl) {
        NodeList nodeList = null;
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(requestUrl);
            nodeList = doc.getElementsByTagName("Title");            
        } catch (Exception e) {
            System.out.println("Message is " + e.getCause() + "...." + e.getMessage());
            throw new RuntimeException(e);
        }
        return nodeList;
    }

我在 main() 中打印为

titleList = fetchTitle(requestUrl);        
        for (int i = 0; i < titleList.getLength(); i++) {
            Node node = titleList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                // do something with the current element
                System.out.println(node.getNodeName()); 
                System.out.println("Signed Title is \"" + node.getTextContent() + "\"");
                System.out.println();
            }

        }

Amount 来自 LowestNewPrice 节点的值

private static NodeList fetchPrice(String requestUrl) {
        NodeList nodeList = null;
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(requestUrl);
            nodeList = doc.getElementsByTagName("LowestNewPrice");           
        } catch (Exception e) {
            System.out.println("Message is " + e.getCause() + "...." + e.getMessage());
            throw new RuntimeException(e);
        }
        return nodeList;
    }

我在 main() 中打印为

priceList = fetchPrice(requestUrl);

        for (int i = 0; i < priceList.getLength(); i++) {
            Node node = priceList.item(i).getFirstChild();
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                // do something with the current element
                System.out.println(node.getNodeName()); 
                System.out.println("Signed Price is \"" + node.getTextContent() + "\"");
                System.out.println();
            }

        }

通过上面的代码,我首先获取所有 Title 值,然后分别获取 Amount 值,但我真正想要的是拥有一个 POJO 类

public class Item {

    String title;
    String price;

    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getPrice() {
        return price;
    }
    public void setPrice(String price) {
        this.price = price;
    }

}

并使用setTitle(), setPrice() 向Item 对象添加值,并返回List&lt;Item&gt; 请帮忙。

【问题讨论】:

    标签: java xml domparser


    【解决方案1】:

    可能请尝试此解决方案。 解析您的数据并添加到List&lt;Item&gt; as:

    public static Document fetchRequiredData(String src) {
        Document doc = null;
    
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder parser;
    
        try {
            parser = dbFactory.newDocumentBuilder();
            doc= parser.parse(src);
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        return doc;
    }
    
    public static List<Item>  parseItemInfo(Document doc){
    
        List<Item> items = new ArrayList<Item>();
        NodeList itemNodeList = doc.getElementsByTagName("Item");       
    
        for (int i = 0; i < itemNodeList.getLength(); i++) {
    
            Node titleNode = doc.getElementsByTagName("Title").item(i);
            Node priceNode = doc.getElementsByTagName("LowestNewPrice").item(i).getFirstChild();
    
            if (titleNode.getNodeType() == Node.ELEMENT_NODE || priceNode.getNodeType() == Node.ELEMENT_NODE ) {
                Item item = new Item();
                item.setDesc(titleNode.getTextContent());
                item.setPrice(priceNode.getTextContent());
                items.add(item);
            }
        }
        return items;
    }
    

    现在您的列表已准备好在main() 方法中进行测试

    public static void main(String[] args) {
         List<Item> items = parseItemInfo(fetchRequiredData(requestUrl));
         System.out.println("Printing List<Item> contents ...");
         for (Item item : items) {
             System.out.println("Title is " + item.getTitle()); 
             System.out.println("Price is " + item.getPrice());
             System.out.println();
         }
    }
    

    希望这篇文章有所帮助。

    【讨论】:

    • 这是一种有效的方法,但如果有&lt;Item&gt; 元素而没有&lt;Title&gt;&lt;LowestNewPrice&gt; 元素,它就会失败。
    • 正如上面提供的 xml stub 所讨论的那样,我想不太可能有任何这样的情况,其中可能存在 &lt;Item&gt; 元素而没有 &lt;Title&gt; 或 @987654330 @元素。感谢您的考虑,但上述答案是否可以改进以避免这种情况,我认为这个答案对于 readwrite 来说是 easy compile 并完成所需的工作。是不是……?
    • 你说得对,就像我说的“这是一种有效的方法”,我只是想指出这一点,让 OP 意识到这一点,以便他可以修改代码如果他的用例包括这类项目。
    • 感谢感谢
    【解决方案2】:

    您可以通过使用 JAXBContext 来实现。首先创建 Item 类。

    @XmlRootElement(name = "Items")
    @XmlAccessorType(value = XmlAccessType.FIELD)
    public class Items
    {
        @XmlElement(name = "Item")
        private List<Item> item;
    
        public void setItem(List<Item> itemList)
        {
            this.item = itemList;
        }
        public List<Item> getItem()
        {
            return this.item;
        }
    }
    
    @XmlRootElement(name = "Item")
    @XmlAccessorType(vallue = XmlAccessType.FIELD)
    public class Item
    {
        @XmlElement(name = "MediumImage")
        private MediumImage image;
        @XmlElement(name = "Title")
        private String title;
        @XmlElement(name = "OfferSummary")
        private OfferSummary summary;
    
        getters();
        setters();
    }
    
    @XmlRootElement(name = "MediumImage")
    @XmlAccessorType(value = XmlAccessType.FIELD)
    public class MediumImage
    {
        @XmlElement(name = "URL")
        private String url;
        ....
    }
    
    @XmlRootElement(name = "OfferSummary")
    @XmlAccessorType(value = XmlAccessType.FIELD)
    public class OfferSummary
    {
        @XmlElement(name = "LowestNewPrice")
        private LowestNewPrice lowestPrice;
        ....
    }
    

    然后从 main 方法中使用 marshaller 和 unmarshaller 方法。

    public static void main(String[] args)
    {
        File xmlFile = new File("file path");
        JAXBContext context = JAXBContext.newInstance(Items.class);
        //To get POJO from xml
        Unmarshaller unmarshaller = context.createUnmarshaller();
        Items items = (Items) unmarshaller.unmarshal(xmlFile);
    }
    

    【讨论】:

      【解决方案3】:

      目前您似乎将价格和标题分成 2 个列表,如果您想将商品的价格和标题存储到单个 Item 对象中,您可以执行以下操作:

      public class Item {
      
          public static void main(String[] args) {
              ArrayList<Item> items = new ArrayList<Item>();
              try {
                  DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
                  DocumentBuilder db = dbf.newDocumentBuilder();
                  Document doc = db.parse(new File("items.xml"));
                  NodeList itemElements = doc.getElementsByTagName("Item");
      
                  for (int i = 0; i < itemElements.getLength(); i++) {
                      Node itemElement = itemElements.item(i);
                      NodeList itemChildren = itemElement.getChildNodes();
      
                      Item item = new Item();
      
                      for (int j = 0; j < itemChildren.getLength(); j++) {
                          Node n = itemChildren.item(j);
                          if (n.getNodeName().equalsIgnoreCase("title")) {
                              item.setTitle(n.getTextContent());
                          } else if (n.getNodeName().equalsIgnoreCase("OfferSummary")) {
                              NodeList offerChildren = n.getChildNodes();
                              for (int k = 0; k < offerChildren.getLength(); k++) {
                                  Node offerChild = offerChildren.item(k);
                                  if (offerChild.getNodeName().equalsIgnoreCase("LowestNewPrice")) {
                                      item.setPrice(offerChild.getTextContent());
                                  }
                              }
                          }
                      }
                      items.add(item);
      
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
              System.out.println("items: " + items);
          }
      
          String title;
          String price;
      
          public String getTitle() {
              return title;
          }
      
          public void setTitle(String title) {
              this.title = title;
          }
      
          public String getPrice() {
              return price;
          }
      
          public void setPrice(String price) {
              this.price = price;
          }
      
          @Override
          public String toString() {
              return "Title: " + title + " Price: " + price;
          }
      
      }
      

      这样做的目的是从 XML 中获取所有 &lt;Item&gt; 元素并循环遍历它们以获取商品的标题和价格。

      【讨论】:

        猜你喜欢
        • 2018-08-03
        • 1970-01-01
        • 1970-01-01
        • 2022-06-28
        • 1970-01-01
        • 2018-04-11
        • 2018-03-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多