XML解析代码从主方法抽取至独立方法后返回空NodeList的问题求助
问题分析与解决方案:抽取XML解析代码后NodeList遍历无输出
你遇到的问题核心在于**getBuyPrices方法中对currencySellPriceList的赋值逻辑错误**,咱们来拆解一下:
在你的方法里,每次循环遍历<Currency>节点时,都会执行:
currencySellPriceList= mainTag.getElementsByTagName("ForexSelling");
这意味着currencySellPriceList会被每次循环覆盖,最终方法返回的只是最后一个<Currency>节点下的ForexSelling节点列表。如果最后一个<Currency>节点没有ForexSelling子节点,或者该列表为空,那么在main方法中遍历这个返回值自然就没有任何输出。
而你最初在main方法中的逻辑是对每个<Currency>节点下的ForexSelling、ForexBuying、CurrencyName都做了处理,并没有覆盖变量,所以能正常输出所有节点的内容。
解决方案1:收集所有ForexSelling节点到列表中(推荐)
如果你的目标是获取所有<Currency>下的ForexSelling节点,改用List<Node>来收集所有符合条件的节点会更直观(因为NodeList是和原Document绑定的,无法直接合并多个NodeList):
修改XMLScraperBuilder的getBuyPrices方法:
import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.xml.sax.SAXException; public class XMLScraperBuilder { public List<Node> getBuyPrices() throws IOException, SAXException, ParserConfigurationException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); List<Node> allSellPrices = new ArrayList<>(); // 用列表收集所有节点 DocumentBuilder builder=factory.newDocumentBuilder(); Document doc = builder.parse("15122021.xml"); NodeList currencyList= doc.getElementsByTagName("Currency"); for(int i=0;i<currencyList.getLength();i++){ Node currency = currencyList.item(i); if(currency.getNodeType()==Node.ELEMENT_NODE){ Element mainTag = (Element) currency; NodeList currencySellPriceList= mainTag.getElementsByTagName("ForexSelling"); // 遍历当前Currency下的ForexSelling节点,加入列表 for(int j=0;j<currencySellPriceList.getLength();j++){ allSellPrices.add(currencySellPriceList.item(j)); } } } return allSellPrices; } }
然后在main方法中遍历这个List:
XMLScraperBuilder scraper = new XMLScraperBuilder(); List<Node> sellPrices = scraper.getBuyPrices(); for(Node node : sellPrices){ if(node.getNodeType() == Node.ELEMENT_NODE){ System.out.println("Sell price: " + node.getTextContent()); } }
解决方案2:封装完整的货币价格数据(更优)
如果你的需求是同时获取货币名称、买入价、卖出价,建议封装一个实体类来存储这些信息,这样代码的可读性和可维护性会更好:
// 定义实体类存储货币价格信息 class CurrencyPrice { private String name; private String buyPrice; private String sellPrice; public CurrencyPrice(String name, String buyPrice, String sellPrice) { this.name = name; this.buyPrice = buyPrice; this.sellPrice = sellPrice; } @Override public String toString() { return "Currency name: " + name + "\nBuy price: " + buyPrice + "\nSell price: " + sellPrice; } }
然后修改方法返回List<CurrencyPrice>:
public List<CurrencyPrice> getCurrencyPrices() throws IOException, SAXException, ParserConfigurationException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); List<CurrencyPrice> currencyPrices = new ArrayList<>(); DocumentBuilder builder=factory.newDocumentBuilder(); Document doc = builder.parse("15122021.xml"); NodeList currencyList= doc.getElementsByTagName("Currency"); for(int i=0;i<currencyList.getLength();i++){ Node currency = currencyList.item(i); if(currency.getNodeType()==Node.ELEMENT_NODE){ Element mainTag = (Element) currency; NodeList nameList = mainTag.getElementsByTagName("CurrencyName"); NodeList buyList = mainTag.getElementsByTagName("ForexBuying"); NodeList sellList = mainTag.getElementsByTagName("ForexSelling"); // 假设每个Currency下这三个节点的数量一致 for(int j=0;j<nameList.getLength();j++){ String name = nameList.item(j).getTextContent(); String buy = buyList.item(j).getTextContent(); String sell = sellList.item(j).getTextContent(); currencyPrices.add(new CurrencyPrice(name, buy, sell)); } } } return currencyPrices; }
在main方法中直接遍历输出:
XMLScraperBuilder scraper = new XMLScraperBuilder(); List<CurrencyPrice> prices = scraper.getCurrencyPrices(); for(CurrencyPrice price : prices){ System.out.println(price); System.out.println("---"); }
内容的提问来源于stack exchange,提问作者Epitaph
相关产品推荐
相关产品推荐

