最快的方式在PHP中显示数据节点及其所有属性?

时间:2011-06-08 17:09:10

标签: php optimization dom

我正在使用php获取xml文件并将它们转换为带有设置列的单行制表符分隔的纯文本(即如果数据库不需要它则忽略某些标记,并且某些标记将为空)。我遇到的问题是需要13分钟才能完成56k(+更改)文件,我认为这些文件速度非常慢。 (平均文件夹有超过一百万个xml文件)我可能会在一夜之间完成cronjob,但是当我正在为丢失文件和损坏的文件等工作时,它在合理的速度下是完全不可测试的。

这里希望有人可以帮我把事情做得更快,xml文件本身不是太大(< 1k行),我不需要每一个数据标签,只有一些,这里是我的数据节点方法:

function dataNode ($entries) {
    $out = "";

    foreach ($entries as $e) {
        $out .= $e->nodeValue."[ATTRIBS]";
        foreach ($e->attributes as $name => $node)
            $out .= $name."=".$node->nodeValue;
    }

    return $out;
}

其中$ entries是从我需要的节点的XPath查询生成的DOMNodeList。所以问题是,去目标数据节点的最快方法是什么(如果我从XPath查询中有10个关键字节点,那么我需要从该函数打印所有这些节点)并输出nodevalue和它的所有内容属性?

我读here迭代DOMNodeList不是常数时间,但我不能真正使用给出的解决方案因为我想要的节点的兄弟可能是我不需要或不需要的节点在将其写入文件之前调用不同的格式函数,我真的不想在尝试格式化数据的每次迭代中通过巨大的switch语句运行节点。

编辑:我是个白痴,我的处理循环中有写函数,所以每次迭代都要重新打开我写的文件,感谢你们的帮助,我现在正在努力学习XSLT因为它看起来非常有用。

1 个答案:

答案 0 :(得分:2)

评论会有点短,所以我把它写成答案:

很难说您的设置实际上可以从优化中获益。也许在加载之前可以将多个XML文件连接在一起。

根据您在问题中提供的信息,我会假设磁盘操作花费的时间比XML解析更多。我发现DomDocument和Xpath甚至在大文件上都非常快。加载最多60 MB的XML文件大约需要4-6秒才能加载,2MB的文件只需要一小部分。

拥有许多小文件(<1k)意味着磁盘上的大量工作,打开/关闭文件。另外,我不知道你如何迭代目录/文件,有时这也可以大大加快速度。特别是当你说有数百万个文件节点时。

因此,对于您来说,连接/合并文件可能是一个非常安全的选项,因此可以减少测试转换器的时间。

如果遇到丢失或损坏的文件,则应创建日志并捕获这些错误。因此,您可以让作业运行并在以后检查错误。

此外,如果可能,您可以尝试恢复工作流程。例如。如果发生错误,则保存当前状态,下次可以继续保持此状态。

在评论中对文件运行XSLT的建议也是一个好主意,也可以先转换它们。在中间设置一个新层来转置数据可以帮助减少整体问题,因为它可以降低复杂性。

到目前为止,这个关于XML文件的工作流程帮助了我:

  1. 预处理文件(纯文本过滤器,可选)
  2. 解析XML。这是加载到DomDocument,XPath迭代等。
  3. 如果找到,我的Parser会发送包含已解析数据的事件。
  4. 如果遇到的数据不是预期的格式,则Parser会抛出特定的异常。这允许在自己的解析器中实现错误。
  5. 其他所有错误也会转换为例外。
  6. 可以捕获异常并完成操作。例如。转到下一个文件等。
  7. Logger,Resumer和Exporter(文件导出)可以挂钩事件。访客模式的排序。
  8. 我已经构建了这样一个系统来处理更大格式的XML文件。它足够灵活,可以处理更改(例如,在保留日志记录和导出的同时用新版本替换解析器)。事件系统真的为我推了它。

    在迭代domnodelist时,我通常使用$state变量来解析器状态,而不是巨大的switch语句。 $state可以方便以后恢复操作。恢复状态并转到上一个已知位置,然后继续。