dom4j解析xml重复节点

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dom4j解析xml重复节点相关的知识,希望对你有一定的参考价值。

xml如下
<?xml version="1.0" encoding="UTF-8"?>
<PACKET type="RESPONSE" version="1.0">
<BODY>
<EDOR_LIST>
<EDOR>
<EDORNO></EDORNO>
<EDORVALIDATE></EDORVALIDATE>
<EDORTYPE></EDORTYPE>
</EDOR>
<EDOR>
<EDORNO></EDORNO>
<EDORVALIDATE></EDORVALIDATE>
<EDORTYPE></EDORTYPE>
</EDOR>
……<!—多条循环 -->
</EDOR_LIST>
</BODY>
</PACKET>

如何拿到EDOR_LIST节点下每一个EDOR节点,解析EDOR节点下的所有值

我做到这一步,不知道下一步怎么做了
已经解析出来了,代码如下:
List<Element> backList = doc.selectNodes("/PACKET/BODY/EDOR_LIST");
for(int i=0 ; i<backList.size();i++)

Element backListEle= backList.get(i);
String edorNo=convertNull(backListEle.selectSingleNode("EDORNO").getText());
String edorDate=convertNull(backListEle.selectSingleNode("EDORVALIDATE").getText());
String edorType=convertNull(backListEle.selectSingleNode("EDORTYPE").getText());

解析出来了,该怎么用怎么用,下面那个回答简直无技术含量(从别的贴吧抄的,我看过无数次!故不予采纳!)

参考技术A import java.io.File;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
public class XmlTest2
public static void main(String[] args)
SAXReader reader = new SAXReader();
reader.setEncoding("UTF-8");
Document doc = null;
try
File file = new File("test2.xml");
doc = reader.read(file);
printNode(doc.selectNodes("DSExport/Job"));

catch (DocumentException e)
e.printStackTrace();


public static void printNode(List<Node> nodeList)
for (Node jobNode : nodeList)
printProperty(jobNode.selectNodes("Record/Property"));
printProperty(jobNode.selectNodes("Record/Collection/SubRecord/Property"));


public static void printProperty(List<Node> propertyNodeList)
for (Node propertyNode : propertyNodeList)
System.out.println(propertyNode.getUniquePath() + ">>" + propertyNode.selectSingleNode("@Name").getText() + ":" + propertyNode.getText());


SQL XML解析不同节点

【中文标题】SQL XML解析不同节点【英文标题】:SQL XML parsing different nodes 【发布时间】:2019-10-24 15:35:02 【问题描述】:

我想请你帮忙解析 SQL 中的 XML,我的 XML 看起来像这样,其中 Load 是可以重复 X 次的父项。我需要 Column SerNr 并且每一行都需要绑定订单名称 决赛桌看起来像这样

表格示例:

<ImageHistory>    
    <Load targets="2" totalTime="417">
    <Orders>
    <Order name="20548976"/>
    </Orders>
    <Data>
    <Disk SerNr="XXXXXX" Size_mb="228936" LoadSuccessfull="true" /> 
    <Disk SerNr="ZZZZZ" Size_mb="228936" LoadSuccessfull="true" /> 
    </Data>
    </Load>
    </ImageHistory>

sql是

with data as (SELECT CAST(MY_XML AS xml) as MY_XML FROM OPENROWSET(BULK 'addres to xml', SINGLE_BLOB) AS T(MY_XML)), 
datainfo as (
SELECT
MY_XML.Blasting.value(' @name', 'BIGINT') as Size_mb,
MY_XML.Blasting.value('@SerNr', 'varchar(32)') as SerNr
FROM data CROSS APPLY MY_XML.nodes('ImageHistory/Load/Data/Disk') AS MY_XML (Blasting))
select * from datainfo 

谢谢你的帮助

【问题讨论】:

【参考方案1】:

我将 XML 保存为文件系统上的文件:e:\Temp\DiskSerialNumbers.xml 其余的在下面。

SQL

;WITH XmlFile (Contents) AS
(
   SELECT CAST(BulkColumn AS XML) 
   FROM OPENROWSET(BULK 'e:\Temp\DiskSerialNumbers.xml', SINGLE_BLOB) AS XmlData
)
SELECT c.value('(../../Orders/Order/@name)[1]', 'INT') AS [Name]
    , c.value('@SerNr', 'VARCHAR(20)') AS [SerNr]
FROM XmlFile CROSS APPLY Contents.nodes('/ImageHistory/Load/Data/Disk') AS t(c);

输出

+----------+--------+
|   Name   | SerNr  |
+----------+--------+
| 20548976 | XXXXXX |
| 20548976 | ZZZZZ  |
+----------+--------+

【讨论】:

嗨 Yitzhak,我刚刚添加了一个替代方案,因为向后导航是性能杀手... 嗨,Shnugo,很划算。我非常清楚向后 XPath 导航是性能杀手。提供的 XML 示例非常小,所以我没有费心使用两个 CROSS APPLY 子句...【参考方案2】:

你已经有了答案,但我想指出一个事实,向后导航(使用../../)是horribly slow with bigger structures。

我建议这样做:

模拟您的问题的模型

DECLARE @yourTable TABLE(ID INT IDENTITY,YourXml XML);
INSERT INTO @yourTable VALUES 
(N'<ImageHistory>
    <Load targets="2" totalTime="417">
    <Orders>
        <Order name="20548976" />
    </Orders>
    <Data>
        <Disk SerNr="XXXXXX" Size_mb="228936" LoadSuccessfull="true" />
        <Disk SerNr="ZZZZZ" Size_mb="228936" LoadSuccessfull="true" />
    </Data>
    </Load>
</ImageHistory>');

--查询

SELECT t.ID
        ,ld.value('@targets','int') AS Load_Targets
        ,ld.value('@totalTime','int') AS Load_TotalTime
        ,ld.value('(Orders/Order/@name)[1]','int') AS Order_Name
        ,dsk.value('@SerNr','nvarchar(100)') AS Disk_SerNr
        ,dsk.value('@Size_mb','nvarchar(100)') AS Disk_Size_mb
        ,dsk.value('@LoadSuccessfull','bit') AS Disk_LoadSuccessfull
FROM @yourTable AS t
CROSS APPLY t.YourXml.nodes('/ImageHistory/Load') A(ld)
CROSS APPLY A.ld.nodes('Data/Disk') B(dsk); 

简而言之:

第一个APPLY 将下潜到&lt;Load&gt; 并将返回所有&lt;Load&gt; 元素(如果还有更多...

第二个APPLY 将使用第一个APPLY 返回的片段并深入到&lt;Disk&gt;

我们针对第一个片段(即&lt;Load&gt; 元素)调用.value() 获取订单名称(和其他值),并针对第二个@ 的片段调用.value() 获取&lt;Disk&gt; 的值987654335@。

【讨论】:

以上是关于dom4j解析xml重复节点的主要内容,如果未能解决你的问题,请参考以下文章

JavaEE XML DOM4J解析

dom4j递归解析XML字符串所有子节点

200分求解:dom4j 使用XPATH解析。。诡异的问题

学习笔记关于DOM4J:使用DOM4J解析XML文档

dom4j 添加节点

dom4j 解析生成xml 案例