我需要处理一堆非常大的XML文件并深度读取每个元素。由于大小的原因,任何DOM
解决方案都是不可能的,因为所需的实际元素不是“叶子”而是其父级,因此事情变得更加复杂。
更具体地说,文件具有类似
的结构 <Level 1>
...
<Level 2>
...
<Level N-1>
<value>...</value>
<value>...</value>
...
<value>...</value>
</Level N-1>
<Level N-1>
<value>...</value>
<value>...</value>
...
<value>...</value>
</Level N-1>
...
<Level N-1>
<value>...</value>
<value>...</value>
...
<value>...</value>
</Level N-1>
...
</Level 2>
</Level 1>
在如上所述的每个文件中,需要单独读取<Level N-1>
元素(每个元素包括所有相应的<value>
元素)。深度N
在每个文件和文件中都有所不同,因此它们基本上是未知的,XML
标记名称也是如此。由于<value>
元素也存在于更高层次(即它们不能保证已达到Level N
),事情变得更加复杂。
将特定深度的整个XML元素作为字符串读取的快速解决方案类似于
int level = 0; // The base level of the element, could be at any depth
Reader in = ... // The reader to the input
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
PrintStream out = new PrintStream(outStream);
XMLEventReader reader = XMLInputFactory.newInstance().createXMLEventReader(in);
XMLEventWriter writer = XMLOutputFactory.newInstance().createXMLEventWriter(out);
XMLEvent event;
while ((level > 0) && reader.hasNext());
{
event = reader.nextEvent();
if (event.isStartElement())
{
level++;
}
else if (event.isEndElement())
{
level--;
}
writer.add(event);
}
writer.flush();
String element = new String(outStream.toByteArray());
但是,如果调用代码不知道已到达Level N-1
元素并且它前进到Level N
(即,到<value>
元素),则上述内容无效。
SAX
解决方案是理想的,但即使是通过XSLT
模板预处理文件也是可以接受的。
有什么想法吗?
答案 0 :(得分:3)
在纯XSLT 1.0或XSLT 2.0中无法进行有用的XSLT预处理,因为XSLT处理器(1.0或2.0)通常会在内存中生成整个XML文档的表示(不一定是DOM)。
在 XSLT 3.0 (仍然是WD)中,将会有流式传输作为语言的一部分,但W3C XSLT WG仍在积极开发这个规范尚未实现稳定。
Saxon以流媒体模板的形式 streaming extensions 处于“可流式模式”:
<xsl:mode name="s" streamable="yes"/>
使用它可以生成XML文档,每个文档只包含以“Level N-1”元素为根的子树。
答案 1 :(得分:1)
如果我已正确理解您的问题,那么当您获得<value>
标记并完成了关卡标记后,您就难以区分
当您识别某个事件时,您可以获得更多信息,例如名称:
if (event.isStartElement()) {
StartElement element = (StartElement) event;
System.out.println("Start Element: " + element.getName());
}
如果您真正想要的是此前的最后一级,当然您必须坚持下去。