如何从大于可用内存的XML文件中删除XML元素/节点?

7

我正在尝试弄清楚如何在PHP(最新版本)中从非常大的XML文件中删除元素(和其子元素)。

我知道我可以使用dom和simpleXml,但那将需要将整个文档加载到内存中。

我正在查看XML writer / reader / parser函数并进行谷歌搜索,但似乎没有关于此主题的内容(所有答案都建议使用dom或simpleXml)。这不可能是正确的-我错过了什么吗?

我找到的最接近的内容是(C#):

您可以使用XmlReader逐个读取xml(ReadOuterXml在您的情况下可能有用以一次读取整个节点)。然后使用XmlWriter编写要保留的所有节点。(从大型XML文件中删除节点

真的吗?就是这种方法吗?我必须复制整个巨大的文件吗?

难道真的没有其他方法吗?

一种方法

如建议所示,

我可以使用php的XML读取器或解析器读取数据,可能会缓冲它,并将其写入/转储 + 追加回新文件中。

但是这种方法真的实用吗?

我曾经尝试过使用建议的方法将巨大的XML文件拆分成较小的部分,但是这个过程花费了很长时间。

我的数据集目前还不够大,无法让我了解如何处理它。我只能假设结果将是相同的(一个非常慢的过程)。

有人有将此应用于实践的经验吗?


XML文件的大小是否比你的RAM大? - Gundars Mēness
理论上是的。我正在尝试找出一种处理大型XML结构的方法,假设如果当前大小不大于内存,则最终会变得更大。 - user1267259
1个回答

3

有几种方法可以逐步处理大型文档,这样您就不需要一次性将整个结构加载到内存中。在任何情况下,是的,您需要将要保留的元素写回并省略您想要删除的元素。

  1. PHP提供了一个XMLReader实现的拉取解析器说明:

    拉取解析器创建一个迭代器,以依次访问XML文档中的各种元素、属性和数据。使用此迭代器的代码可以测试当前项(例如,判断它是开始或结束元素、还是文本),并检查其属性(本地名称、命名空间、XML属性值、文本值等),还可以将迭代器移动到下一个项。因此,代码可以在遍历文档时从中提取信息。

  2. 或者你可以使用SAX XML解析器说明:

    XML简单应用程序接口(SAX)是一种词法、事件驱动的接口,在其中顺序读取文档,并将其内容作为回调报告给用户设计的处理程序对象的各种方法。SAX实现快速高效,但对于随机提取XML信息而言较难使用,因为它往往会让应用程序开发者负担跟踪正在处理文档的哪个部分。

很多人更喜欢使用拉取方法,但两种方法都能满足您的要求。请记住,大的概念是相对的。如果文档适合内存,则几乎总是更容易使用DOM。但对于非常、非常大的文档,这可能不是一个选项。

我已经搜索了很久,但似乎这是在php中唯一的方法。目前我必须采用这种方式,但当文件开始达到GB级别时,我仍然感到不安。我将接受您的答案作为已接受的解决方案,直到出现更好的方法 =) - user1267259
这并不是在PHP中唯一的处理方式。SAX解析所需的内存与树的深度成正比,而树的深度通常远远小于整个文档的大小。 - Wayne
我不明白。你能再解释一下吗?请记住,假设内存不足以支持该进程。 - user1267259

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接