2012-09-19 49 views
2

我需要处理一堆非常大的XML文件并深度优先读取每个元素。由于尺寸大小,任何解决方案都不存在问题,并且事实由于所需的实际元素不是“叶子”而是其父亲的事实而变得更加复杂。深度首次读取大型XML文件

更具体地,文件具有类似

<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>元素)。

A SAX解决方案将是理想的,但即使通过XSLT模板预处理文件也是可以接受的。

任何想法?

+0

您是否可以用示例输入和期望输出来澄清要求? –

+0

上面的数据描述中没有太多要添加的内容,只有标签名称会发生​​变化。基本上,这个想法是将每个Level-1标签上的所有元素组合在一起。 – PNS

回答

3

由于XSLT处理器(1.0或2.0)通常会在内存中生成整个XML文档的表示(不一定是DOM),因此在纯XSLT 1.0或XSLT 2.0中无法实现想要的XSLT预处理。

XSLT 3.0(仍然是一个WD)会有流作为语言的一部分,但是这仍然是正在积极开发由W3C XSLT WG和规范还没有稳定。

撒克逊具有streaming extensions在流模板的形式是在一个“流化模式”:

<xsl:mode name="s" streamable="yes"/> 

使用,它可能是能够生产每片含只是植根于一个子树“XML文档级别N-1“元素。

+0

好吧,XSLT意味着预处理,所以它不是这里最好的选择。但即使是这样,鉴于您的顶级XSLT技能,我从上面的描述中认为,没有办法做到这一点。不过谢谢你的回答! :-) – PNS

+0

@PNS,如果您使用撒克逊的流媒体扩展,可以在今天完成。任何XSLT 3.0流处理器都可以在一年内完成。 –

1

如果我理解正确的您的问题,你遇到难以区分,当你得到一个<value>标签,并已完成经历的级别标记

当你认识一个事件,你可以得到这样的名字的更多信息出于此:

if (event.isStartElement()) { 
    StartElement element = (StartElement) event; 
    System.out.println("Start Element: " + element.getName()); 
    } 

如果你真正想要的是在此之前的最后一关,当然你必须坚持下去。

+0

当然,但问题是我需要阅读整个标签,只是阅读元素不能保证已达到。 – PNS