我遇到过这样一种情况,我想从一些非常大但很普通的XML文件(只需要500Mb的文件)中提取一些信息,而XSLT是最好的选择。
这会导致计算机交换到死机状态。
//m/e[contains(.,'foobar')
因此,它本质上只是一个grep。
有没有可以做到这一点的XSLT实现?或者,如果XSLT实现给出了适当的“建议”,它就可以修剪掉内存中不再需要的部分?
我更喜欢Java实现,但Windows和Linux都是可行的本机平台。
编辑:输入的XML如下所示:
<log>
<!-- Fri Jun 26 12:09:27 CEST 2009 -->
<e h='12:09:27,284' l='org.apache.catalina.session.ManagerBase' z='1246010967284' t='ContainerBackgroundProcessor[StandardEngine[Catalina]]' v='10000'>
<m>Registering Catalina:type=Manager,path=/axsWHSweb-20090626,host=localhost</m></e>
<e h='12:09:27,284' l='org.apache.catalina.session.ManagerBase' z='1246010967284' t='ContainerBackgroundProcessor[StandardEngine[Catalina]]' v='10000'>
<m>Force random number initialization starting</m></e>
<e h='12:09:27,284' l='org.apache.catalina.session.ManagerBase' z='1246010967284' t='ContainerBackgroundProcessor[StandardEngine[Catalina]]' v='10000'>
<m>Getting message digest component for algorithm MD5</m></e>
<e h='12:09:27,284' l='org.apache.catalina.session.ManagerBase' z='1246010967284' t='ContainerBackgroundProcessor[StandardEngine[Catalina]]' v='10000'>
<m>Completed getting message digest component</m></e>
<e h='12:09:27,284' l='org.apache.catalina.session.ManagerBase' z='1246010967284' t='ContainerBackgroundProcessor[StandardEngine[Catalina]]' v='10000'>
<m>getDigest() 0</m></e>
......
</log>
本质上,我想选择一些m节点(我知道XPath在这方面是错误的,这只是一个快速的技巧),但要保持XML布局。
编辑:看起来STX可能就是我正在寻找的(我可以使用另一种转换语言),而Joost是它的一个实现。有什么经验吗?
编辑:我发现带有-Xmx1500m的Saxon6.5.4可以加载我的XML,所以现在就可以使用我的XPaths了。
编辑:哦,顺便说一下。这是一个与log4j XMLLayout生成的日志文件非常相似的日志文件。使用XML的原因就是能够做到这一点,即对日志进行查询。这是最初的尝试,因此问题很简单。稍后,我希望能够提出更复杂的问题-因此,我希望查询语言能够处理输入文件。
发布于 2009-12-17 21:46:35
您应该能够在不进行全表扫描的情况下实现这一点。“//”运算符表示在树中查找任意级别的元素。特别是在你这种大小的文档上运行它是相当昂贵的。如果优化XPath查询或考虑设置匹配模板,则XSLT转换器可能不需要将整个文档加载到内存中。
根据您的XML示例,您希望匹配/log/e/m ...谓词...某些XSLT处理程序应该能够对此进行优化,使其不扫描//所不能扫描的整个文档。
因为XML文档非常简单,所以根本不使用XSLT可能更容易。STaX是一个很好的处理大型XML文档的流式应用编程接口。Dom4j还很好地支持对大型文档进行类似XPath的查询。有关在大型文档中使用dom4j的信息,请访问:http://dom4j.sourceforge.net/dom4j-1.6.1/faq.html#large-doc
来自上述来源的示例:
SAXReader reader = new SAXReader();
reader.addHandler( "/ROWSET/ROW",
new ElementHandler() {
public void onStart(ElementPath path) {
// do nothing here...
}
public void onEnd(ElementPath path) {
// process a ROW element
Element row = path.getCurrent();
Element rowSet = row.getParent();
Document document = row.getDocument();
...
// prune the tree
row.detach();
}
}
);
Document document = reader.read(url);
// The document will now be complete but all the ROW elements
// will have been pruned.
// We may want to do some final processing now
...
发布于 2009-12-17 22:27:23
发布于 2009-12-17 21:50:46
这是暗箭伤人,说不定你会把我笑出家门。
没有什么可以阻止您将SAX源连接到XSLT的输入;至少在理论上,从SAX流执行grep并不需要DOM是足够简单的。所以..。想试一试吗?
https://stackoverflow.com/questions/1921876
复制相似问题