Java DOM解析XML筛选supplier为Apple的product节点方法
问题背景
现有一份订单XML文件,需要提取所有<supplier>子节点值为Apple的<product>节点内容。初始编写的Java代码存在逻辑错误,无法得到预期结果。
测试用XML内容如下:
<?xml version="1.0" encoding="UTF-8"?> <orders> <order created='2012-07-12T15:29:33.000' ID='2343'> <product> <description>Sony 54.6" (Diag) Xbr Hx929 Internet Tv</description> <gtin>00027242816657</gtin> <price currency="USD">2999.99</price> <supplier>Sony</supplier> </product> <product> <description>Apple iPad 2 with Wi-Fi 16GB - iOS 5 - Black</description> <gtin>00885909464517</gtin> <price currency="USD">399.0</price> <supplier>Apple</supplier> </product> <product> <description>Sony NWZ-E464 8GB E Series Walkman Video MP3 Player Blue</description> <gtin>00027242831438</gtin> <price currency="USD">91.99</price> <supplier>Sony</supplier> </product> </order> <order created='2012-07-13T16:02:22.000' ID='2344'> <product> <description>Apple MacBook Air A 11.6" Mac OS X v10.7 Lion MacBook</description> <gtin>00885909464043</gtin> <price currency="USD">1149.0</price> <supplier>Apple</supplier> </product> <product> <description>Panasonic TC-L47E50 47" Smart TV Viera E50 Series LED HDTV</description> <gtin>00885170076471</gtin> <price currency="USD">999.99</price> <supplier>Panasonic</supplier> </product> </order> </orders>
原代码问题点
- 节点选取错误:初始代码直接选取根节点
<orders>,没有定位到目标<product>节点 - 元素属性混淆:
<supplier>是<product>下的子元素,不是节点属性,用属性读取的方式无法获取对应值 - 路径转义错误:Windows路径中的反斜杠没有做转义处理,会被Java识别为非法转义字符,导致文件读取失败
可运行实现代码
import org.w3c.dom.*; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.File; import java.io.IOException; import java.io.StringWriter; public class XmlProductParser { public void readXml() throws ParserConfigurationException, SAXException, IOException, TransformerException { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = dbf.newDocumentBuilder(); // 路径推荐用正斜杠,不需要额外转义,避免转义符错误 Document doc = builder.parse(new File("C:/Users/40723/Documents/NetBeansProjects/SACOM/src/sacom/suppliers23.xml")); // 直接获取所有product节点列表 NodeList productList = doc.getElementsByTagName("product"); for (int i = 0; i < productList.getLength(); i++) { Node productNode = productList.item(i); // 跳过空白、注释等非元素节点 if (productNode.getNodeType() != Node.ELEMENT_NODE) { continue; } Element productEle = (Element) productNode; // 读取当前product下supplier节点的文本值 String supplierVal = productEle.getElementsByTagName("supplier").item(0).getTextContent().trim(); // 匹配供应商为Apple的商品 if ("Apple".equals(supplierVal)) { System.out.println("匹配到Apple供应商商品:"); // 输出当前product节点的完整XML内容 TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); StringWriter writer = new StringWriter(); transformer.transform(new DOMSource(productNode), new StreamResult(writer)); System.out.println(writer.getBuffer().toString()); System.out.println("--------------------"); } } } public static void main(String[] args) throws Exception { new XmlProductParser().readXml(); } }
运行说明
代码执行后会输出2个匹配结果,分别对应Apple iPad 2、Apple MacBook Air两个商品的完整product节点内容。如果不需要输出完整XML,也可以直接通过getElementsByTagName方法分别读取description、gtin、price等子节点的值,做后续业务处理。
内容的提问来源于stack exchange,提问作者JohnNewman
相关产品推荐
相关产品推荐

