我想解析具有以下事件的 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>
</xsl:text>
</xsl:template>
</xsl:transform>
注意
我最初将选择表达式编写为copy-of(.)//(name,age,street,nr)
。这是不正确的,因为 //
运算符将结果按文档顺序排序,这是我们不希望的。使用 !
和 ,
小心地避免了排序。
关于java - 如何用DOM解析大型xml文档?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50231072/