gpt4 book ai didi

java - 如何用DOM解析大型xml文档?

转载 作者:行者123 更新时间:2023-12-01 17:50:57 25 4
gpt4 key购买 nike

我想解析具有以下事件的 xml 元素:

  • 并且没有 xml 声明
  • 可以不按特定顺序提供元素
<employees>
<employee>
<details>
<name>Joe</name>
<age>34</age>
</details>
<address>
<street>test</street>
<nr>12</nr>
</address>
</employee>
<employee>
<address>....</address>
<details>
<!-- note the changed order of elements! -->
<age>24</age>
<name>Sam</name>
</details>
</employee>
</employees>

输出应为 csv:

name;age;street;nr
Joe,34,test,12
Sam,24,...

问题:当使用像 stax/sax 这样的事件驱动解析器时,我必须创建一个临时的 Employee我在每个事件节点上设置其属性的 bean,然后将 bean 转换为 csv。

但是由于我的 xml 文件大小有几 GB,我希望避免为每个条目创建额外的 bean 对象。

因此我可能不得不使用普通的旧 DOM解析?如果我错了,请纠正我,我很高兴收到任何建议。

我尝试如下。问题是doc.getElementsByTagName("employees")返回一个空节点列表,而我期望一个 xml 元素。为什么?

StringBuilder sb = new StringBuilder();

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(new StringReader(xml)));
doc.getDocumentElement().normalize();

NodeList employees = doc.getElementsByTagName("employees");
for (int i = 0; i < employees.getLength(); i++) {
Node employee = employees.item(i);
if (employees.getNodeType() == Node.ELEMENT_NODE) {
NodeList employee = ((Element) employees).getElementsByTagName("employee");
for (int j = 0; j < employee.getLength(); j++) {
NodeList details = ((Element) employee).getElementsByTagName("details");

//the rest is pseudocode
for (details)
sb.append(getElements("name").item(0) + ",");
sb.append(getElements("age").item(0) + ",");

for (address)
sb.append(getElements("street").item(0) + ",");
sb.append(getElements("nr").item(0) + ",");
}
}
}

最佳答案

DOM 解决方案将使用大量内存,SAX/Stax 解决方案将涉及编写和调试大量代码。这项工作的理想工具是 XSLT 3.0 可流式转换:

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:mode streamable="yes" on-no-match="shallow-skip"/>
<xsl:template match="employee">
<xsl:value-of select="copy-of(.)!(.//name, .//age, .//street, .//nr)"
separator=","/>
<xsl:text>&#xa;</xsl:text>
</xsl:template>
</xsl:transform>

注意

我最初将选择表达式编写为copy-of(.)//(name,age,street,nr)。这是不正确的,因为 // 运算符将结果按文档顺序排序,这是我们不希望的。使用 !, 小心地避免了排序。

关于java - 如何用DOM解析大型xml文档?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50231072/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com