【问题标题】:Serially process XML data in perl在 perl 中串行处理 XML 数据
【发布时间】:2012-12-17 11:38:19
【问题描述】:

我想知道在我的情况下,哪种 XML 解析器最适合 Perl。我做了很多阅读并尝试了XML::LibXMLXML::SAX。第一个用了太多内存,第二个对我来说似乎没有那么快(即使在关闭纯 perl 解析器之后)。

我的需求相当具体。我通过 Net::SSH 库收到了高达 50MB 的较大响应。我想在收到这些数据时将其传递给 XML 库,以便在内存中保持最少的数据量。然后我需要在某些标签中查找数据并对其进行任何处理,在某些情况下汇总一堆值,在其他情况下只需提取值并将它们写入文件或其他任何内容。所以我需要一个可以连续工作、工作速度快并且使用最少内存的 XML 解析器。我获得的数据最多为 1024 字节,因此我希望能够执行类似 $myparser->sendData($mynewData) 的操作,然后在打开或关闭新标签时调用函数,类似于 XML::SAX 所做的那样。

我不一定需要 XPath 或 XSLT。

【问题讨论】:

    标签: xml linux perl centos


    【解决方案1】:

    XML::LibXML 还带有两个流解析器,它们应该比纯 Perl 解决方案更快:

    XML::LibXML::SAX

    与 XML::SAX 兼容的 SAX 解析器。

    XML::LibXML::Reader

    libxml2 的 pull 解析器的接口。它提供了比 SAX 更简单的接口并且速度更快一些。据我所知,XML::LibXML::Reader 是解析 XML 文件而不将它们完全加载到内存中最快的 Perl 模块。

    【讨论】:

    • 嗨尼克,你知道你是否可以将数据以块的形式传递给 XML::LibXML::SAX?我只能看到一种串行解析文件的方法,但我正在从 perl ssh 库接收数据。类似于 XML::Parser 的 parse_more 函数。
    【解决方案2】:

    您也可以使用普通的旧 XML::Parser,它几乎可以满足您的要求:

    “这个模块提供了解析 XML 文档的方法。它建立在 XML::Parser::Expat 之上,它是 James Clark 的 expat 库的一个较低级别的接口。每次调用其中一个解析方法都会创建一个新的XML::Parser::Expat 的实例,然后用于解析文档。创建 XML::Parser 对象时可能会提供 Expat 选项。然后在每次解析调用时将这些选项传递给 Expat 对象。它们可以也可以作为解析方法的额外参数,在这种情况下,它们会覆盖在 XML::Parser 创建时给出的选项。"

    “Expat 是一个基于事件的解析器。当解析器识别文档的某些部分(比如 XML 元素的开始或结束标记)时,任何为该类型事件注册的处理程序都会使用合适的参数调用。”

    我已经用它来解析Wikipedia XML dumps,即使压缩后也有几 GB 的大小,并且发现它可以很好地解决这个问题。相比之下,一个 50 MB 的文件应该是小菜一碟。

    【讨论】:

    • 谢谢伊尔马里。你多快找到它?我发现 perl 可以加载一个 50MB 的文件并在不到 1 秒的时间内完成搜索,而 XML 解析器似乎都需要大约 20 秒。听起来对吗?
    • 我刚刚尝试运行 one of my old scripts,它在 2 GHz Intel Xeon 服务器上的 1.7 GB 最新芬兰维基百科转储上每秒运行大约 10 MB。
    • XML 解析器比纯正则表达式慢,因为它们考虑了所有各种 XML 编写方式,这需要一些时间。但是,除非您对 XML 的编写方式有 完全 控制权,否则额外的时间将是快速完成和正确完成之间的区别(一个简单的正则表达式可能对诸如标记和使用可忽略的空白,并且可以匹配错误位置的内容,例如在 cmets 中)。
    • @ebohlman 我肯定对使用正则表达式不感兴趣,并认为这是有史以来最大的黑客攻击,但这里有人在工作。我试图找到一种性能相当的解决方案,以便我们可以制作不会因 XML 的细微差异而崩溃的代码。我可以看到至少 10 种正则表达式失败的方式。 20 秒并不是真正的问题,因为响应返回最多需要 3 分钟,我们可以随时处理响应。
    【解决方案3】:

    我建议使用XML::Twig

    这个模块使用起来非常方便,而且它可以在不占用太多内存的情况下串行读取数据。

    XML::Twig 最显着的特点之一可能是它允许在所谓的混合模型中解析 XML:您可以解析整个文档(需要整个文档和大量内存),您可以使用回调来解析小块(允许流式传输,小内存消耗),或者您可以使用这些的任意组合。

    事实证明,这种组合模型是最方便的功能 - 从流中加载小叶子,您可以免费有效地访问它的所有小分支。

    【讨论】:

    • 感谢 mvp 和 @IlmariKaronen 我会尝试这些并在确定哪个效果最好时标记绿色勾号。这可能需要我一段时间:-)
    • 我现在已经测试了几个 xml 解析器(以及仅使用正则表达式),我得到的 50MB 文件的结果是正则表达式不到 1 秒,XML::Parser 21 秒,XML: :SAX 22 秒,树枝 70 秒。在所有情况下,我只是寻找名为“interface”的节点并计算它们。他们所有人的内存使用量都很小。有趣的是,所有解析器都比正则表达式慢得多。我倾向于 XML::Parser,因为它已经安装在服务器上,使用简单而且速度很快。但也许我对 twig 做错了什么?
    • 如果你只是计算节点,你应该使用XML::Twig ignore 方法或类似setIgnoreEltsHandler 的方法——它会大大加快速度,因为不需要构建twig。此外,您应该在回调中调用 purge 方法来释放分配给树枝的内存 - 它会使其更快
    猜你喜欢
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-06
    • 1970-01-01
    相关资源
    最近更新 更多