首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用XSLT进行XML提取,而不必将整个DOM树读取到内存中?

使用XSLT进行XML提取,而不必将整个DOM树读取到内存中?
EN

Stack Overflow用户
提问于 2009-12-17 21:42:12
回答 7查看 2.4K关注 0票数 4

我遇到过这样一种情况,我想从一些非常大但很普通的XML文件(只需要500Mb的文件)中提取一些信息,而XSLT是最好的选择。

这会导致计算机交换到死机状态。

代码语言:javascript
复制
//m/e[contains(.,'foobar')

因此,它本质上只是一个grep。

有没有可以做到这一点的XSLT实现?或者,如果XSLT实现给出了适当的“建议”,它就可以修剪掉内存中不再需要的部分?

我更喜欢Java实现,但Windows和Linux都是可行的本机平台。

编辑:输入的XML如下所示:

代码语言:javascript
复制
<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的原因就是能够做到这一点,即对日志进行查询。这是最初的尝试,因此问题很简单。稍后,我希望能够提出更复杂的问题-因此,我希望查询语言能够处理输入文件。

EN

回答 7

Stack Overflow用户

发布于 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

来自上述来源的示例:

代码语言:javascript
复制
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
...
票数 2
EN

Stack Overflow用户

发布于 2009-12-17 22:27:23

票数 1
EN

Stack Overflow用户

发布于 2009-12-17 21:50:46

这是暗箭伤人,说不定你会把我笑出家门。

没有什么可以阻止您将SAX源连接到XSLT的输入;至少在理论上,从SAX流执行grep并不需要DOM是足够简单的。所以..。想试一试吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1921876

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档