如何解析含重复标签的XML并将数据存入List(Java EE 5)
解析重复标签XML时仅获取第一个值的解决方案
问题场景
现有如下结构的XML,需要将所有<abc:Order>和<abc:Name>的值分别存入对应的List,但当前解析代码仅能获取第一个值。
原XML结构:
<abc:Body> <abc:AssyData> <abc:Order>1</abc:Order> <abc:Name>A</abc:Name> </abc:AssyData> <abc:AssyData> <abc:Order>2</abc:Order> <abc:Name>B</abc:Name> </abc:AssyData> <abc:AssyData> <abc:Order>3</abc:Order> <abc:Name>C</abc:Name> </abc:AssyData> </abc:Body>
当前代码输出:
List<String> orders = [1] List<String> names = [A]
期望输出:
List<String> orders = [1,2,3] List<String> names = [A,B,C]
原代码问题分析
原代码的核心错误是仅遍历了<abc:Body>节点(通常XML中只有一个该节点),然后直接调用item(0)获取第一个<abc:Order>和<abc:Name>的值,完全没有遍历所有包含完整数据的<abc:AssyData>节点,导致只能拿到第一组数据。
原代码:
String order = null; String name = null; List<String> orders = new ArrayList<String>(); List<String> names = new ArrayList<String>(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new File(IDOC));//IDOC是磁盘上的XML文件 doc.getDocumentElement().normalize(); NodeList list = doc.getElementsByTagName("abc:Body"); for (int temp = 0; temp < list.getLength(); temp++) { Node node = list.item(temp); if(node.getNodeType() == Node.ELEMENT_NODE) { Element element = (Element) node; orders.add(element.getElementsByTagName("abc:Order").item(0).getTextContent()); names.add(element.getElementsByTagName("abc:Name").item(0).getTextContent()); } } } catch (Exception e) { e.printStackTrace(); } System.out.println(orders); System.out.println(names);
修改后的代码
核心调整为:直接获取所有<abc:AssyData>节点并遍历,从每个节点中提取对应的数据存入List。
String order = null; String name = null; List<String> orders = new ArrayList<String>(); List<String> names = new ArrayList<String>(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); try { dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); // 开启命名空间支持,避免前缀abc导致节点匹配失败 dbf.setNamespaceAware(true); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(new File(IDOC));//IDOC是磁盘上的XML文件 doc.getDocumentElement().normalize(); // 获取所有abc:AssyData节点,每个节点对应一组Order和Name NodeList assyDataList = doc.getElementsByTagName("abc:AssyData"); for (int i = 0; i < assyDataList.getLength(); i++) { Node assyNode = assyDataList.item(i); if (assyNode.getNodeType() == Node.ELEMENT_NODE) { Element assyElement = (Element) assyNode; // 提取当前AssyData下的Order值,添加空判断避免空指针 Node orderNode = assyElement.getElementsByTagName("abc:Order").item(0); if (orderNode != null) { orders.add(orderNode.getTextContent().trim()); } // 提取当前AssyData下的Name值 Node nameNode = assyElement.getElementsByTagName("abc:Name").item(0); if (nameNode != null) { names.add(nameNode.getTextContent().trim()); } } } } catch (Exception e) { e.printStackTrace(); } System.out.println(orders); System.out.println(names);
关键说明
- 命名空间支持:添加
dbf.setNamespaceAware(true);确保解析器能正确识别带前缀的节点,避免因命名空间问题找不到<abc:AssyData>等节点。 - 遍历数据节点:直接遍历所有
<abc:AssyData>节点,每个节点对应一组完整的Order和Name数据,保证能收集到全部值。 - 空值防护:添加节点非空判断,避免XML中缺失某个标签时触发空指针异常。
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

