PHP的DOM和SimpleXML扩展之间有什么区别?

时间:2011-01-26 09:41:09

标签: php simplexml domdocument

我无法理解为什么我们在PHP中需要2个XML解析器。

有人可以解释这两者之间的区别吗?

5 个答案:

答案 0 :(得分:96)

简而言之:

SimpleXml

  • 适用于简单的XML和/或简单的UseCases
  • 有限的API用于处理节点(例如,无法编程到接口那么多)
  • 所有节点属于同一种类(元素节点与属性节点相同)
  • 节点可以神奇地访问,例如$root->foo->bar['attribute']

DOM

  • 适用于您可能拥有的任何XML UseCase
  • is an implementation of the W3C DOM API(发现以多种语言实施)
  • 区分各种节点类型(更多控制)
  • 由于显式API(可以编码到接口)而更加冗长
  • 可以解析损坏的HTML
  • 允许您在XPath查询中使用PHP函数

这两个都基于libxml,可能会受到libxml functions

的影响

个人,我不太喜欢SimpleXml。那是因为我不喜欢对节点的隐式访问,例如$foo->bar[1]->baz['attribute']。它将实际的XML结构与编程接口联系起来。单节点类型的所有内容也有些不直观,因为SimpleXmlElement的行为根据其内容神奇地改变。

例如,当你有<foo bar="1"/>时,/foo/@bar的对象转储将与/foo的对象转储相同,但对它们进行回显会打印出不同的结果。此外,由于它们都是SimpleXml元素,因此可以对它们调用相同的方法,但只有在SimpleXmlElement支持时才会应用它们,例如:尝试在第一个SimpleXmlElement上执行$el->addAttribute('foo', 'bar')将不执行任何操作。当然,您无法向属性节点添加属性是正确的,但重点是,属性节点首先不会公开该方法。

但那只是我的2c。自己决定:)


旁注上,没有两个解析器,只有a couple more in PHP。 SimpleXml和DOM只是将文档解析为树结构的两个。其他的是基于拉或基于事件的解析器/读者/编写者。

另见

的答案

答案 1 :(得分:39)

我将尽可能做出最短的答案,以便初学者可以轻松地将其拿走。我也为了简短而略微简化了一些事情。跳过那个夸大的TL; DR版本的答案的结尾。


DOM和SimpleXML 实际上并不是两种不同的解析器。真正的解析器是libxml2,由DOM和SimpleXML内部使用。所以DOM / SimpleXML只是使用同一个解析器的两种方式,它们提供了将one object转换为another的方法。

SimpleXML 旨在非常简单,因此它具有一小部分功能,并且专注于读取和写入数据。也就是说,您可以轻松地读取或写入XML文件,您可以update some values或删除一些节点(with some limitations!),就是这样。 没有花哨的操作,并且您无法访问不太常见的节点类型。例如,SimpleXML无法创建CDATA部分,尽管它可以读取它们。

DOM 提供了{strong>全面实施的DOM 以及一些非标准方法,例如appendXML。如果您习惯在Javascript中操作DOM,那么您将在PHP的DOM中找到完全相同的方法。你可以做什么基本上没有限制,它平均处理HTML。这种丰富功能的另一面是它比SimpleXML 更复杂更冗长。


边注

人们常常想/他们应该使用什么扩展来处理他们的XML或HTML内容。实际上选择很容易,因为开始时没有太多选择:

  • 如果你需要处理HTML,你真的没有选择:你必须使用DOM
  • 如果您必须做任何花哨的事情,例如移动节点或附加一些原始XML,那么你几乎 使用DOM
  • 如果您只需要阅读和/或编写一些基本的XML(例如,使用XML服务交换数据或阅读RSS源),那么您可以使用其中任何一种。 Or both
  • 如果您的XML文档太大而不适合内存,那么您也不能使用它们而必须使用基于libxml2的XMLReader,更令人讨厌,但仍然plays nice with others

TL; DR

  • SimpleXML非常易于使用,但仅适用于90%的用例。
  • DOM更复杂,但可以做任何事情。
  • XMLReader非常复杂,但使用的内存非常少。非常情绪化。

答案 2 :(得分:3)

正如其他人所指出的那样,DOM和SimpleXML扩展并不是严格的“XML解析器”,而是它们与底层libxml2解析器生成的结构的不同接口。

SimpleXML接口将XML视为序列化数据结构,与处理解码的JSON字符串的方式相同。因此,它可以快速访问文档的内容,重点是按名称访问元素,并读取其属性和文本内容(包括在实体和CDATA部分中自动折叠)。它支持包含多个名称空间的文档(主要使用children()attributes()方法),并且可以使用XPath表达式搜索文档。它还包括对内容的基本操作的支持 - 例如使用新字符串添加或覆盖元素或属性。

另一方面,DOM接口将XML视为结构化文档,其中使用的表示与表示的数据一样重要。因此,它提供了对不同类型的“节点”的更细粒度和显式的访问,例如实体和CDATA部分,以及一些被SimpleXML忽略的部分,例如注释和处理指令。它还提供了更丰富的操作函数集,允许您重新排列节点并选择如何表示文本内容。权衡是一个相当复杂的API,具有大量的类和方法;因为它实现了一个标准API(最初是为在JavaScript中操作HTML而开发的),所以可能没有“自然PHP”的感觉,但是一些程序员可能会从其他上下文中熟悉它。

两个接口都需要将完整的文档解析到内存中,并有效地将指针包装到解析后的表示中;您甚至可以使用simplexml_import_dom()dom_import_simplexml()在两个包装器之间切换,例如使用DOM API中的函数向SimpleXML添加“缺失”功能。对于较大的文档,“基于拉取”XMLReader或“基于事件的”XML Parser可能更合适。

答案 3 :(得分:2)

正如名称所示,SimpleXML是XML内容的简单解析器,而不是其他任何东西。你不能解析,让我们说标准的HTML内容。它简单快捷,因此是创建简单应用程序的绝佳工具。

另一方面,DOM扩展功能更强大。它使您能够解析几乎任何DOM文档,包括html,xhtml,xml。它使您能够打开,写入甚至更正输出代码,支持xpath和整体更多操作。 因此,它的使用要复杂得多,因为库非常复杂,这使得它成为需要大量数据操作的大型项目的完美工具。

希望能回答你的问题:)

答案 4 :(得分:2)

哪些DOMNode可以由SimpleXMLElement表示?

两个库之间最大的区别是SimpleXML主要是单个类:SimpleXMLElement。相比之下,DOM扩展有许多类,其中大多数是DOMNode的子类型。

因此,在比较这两个库时,一个核心问题是DOM提供的许多类中的哪一个最终可以用SimpleXMLElement表示?

以下是一个比较表,其中包含那些在处理XML时实际有用的DOMNode类型(有用的节点类型)。您的里程可能会有所不同当你需要处理DTD时,例如:

+-------------------------+----+--------------------------+-----------+
| LIBXML Constant         |  # | DOMNode Classname        | SimpleXML |
+-------------------------+----+--------------------------+-----------+
| XML_ELEMENT_NODE        |  1 | DOMElement               |    yes    |
| XML_ATTRIBUTE_NODE      |  2 | DOMAttr                  |    yes    |
| XML_TEXT_NODE           |  3 | DOMText                  |  no [1]   |
| XML_CDATA_SECTION_NODE  |  4 | DOMCharacterData         |  no [2]   |
| XML_PI_NODE             |  7 | DOMProcessingInstruction |    no     |
| XML_COMMENT_NODE        |  8 | DOMComment               |    no     |
| XML_DOCUMENT_NODE       |  9 | DOMDocument              |    no     |
| XML_DOCUMENT_FRAG_NODE  | 11 | DOMDocumentFragment      |    no     |
+-------------------------+----+--------------------------+-----------+
  • [1]:SimpleXML将文本节点抽象为元素的字符串值(比较              __toString)。这只适用于              元素仅包含文本,否则文本信息可能会丢失。
  • [2]:每个XML Parser都可以在加载文档时扩展CDATA节点。 SimpleXML扩展了这些              LIBXML_NOCDATA optionsimplexml_load_* functions一起使用              constructor或              DOMDocument::loadXML()。 (选项也适用于              Traversable

如该表所示,与DOM相比,SimpleXML的界面非常有限。在表格中,SimpleXMLElement还抽象出对子项和属性列表的访问,并通过元素名称(属性访问),属性(数组访问)以及How to tell apart SimpleXML objects representing element and attribute?提供遍历。迭代它的“自己的”子元素(元素或属性)并通过children()attributes()方法提供命名空间访问。

只要所有这个神奇的界面都很好,但是它不能通过从SimpleXMLElement扩展来改变,所以尽可能神奇,因为它也是有限的。

要找出SimpleXMLElement对象所代表的节点类型,请参阅:

XPath 1.0。您可以使用该接口执行几乎所有可以想象的XML处理。然而它只是1级,所以与现代DOMDocument Levels(如3)相比,它对某些更酷的东西有些限制。当然SimpleXML也在这里丢失了。

SimpleXMLElement允许转换为子类型。这在PHP中非常特殊。 DOM也允许这样做,虽然它需要更多的工作,并且需要选择更具体的节点类型。

两者都支持

,SimpleXML中的结果是array SimpleXMLElements,在DOM中DOMNodelist

SimpleXMLElement支持转换为字符串和数组(json),DOM中的DOMNode类不支持。它们提供了转换为数组,但是只像其他任何对象一样(公共属性作为键/值)。

PHP中这两个扩展的常见用法模式是:

  • 您通常会开始使用SimpleXMLElement。您对XML和XPath的知识水平处于同样低的水平。
  • 在与界面的魔力作斗争之后,迟早会达到一定程度的挫败感。
  • 您发现可以将SimpleXMLElement导入DOM,反之亦然。您可以了解有关DOM的更多信息以及如何使用扩展来执行您无法(或无法了解如何)处理SimpleXMLElement的内容。
  • 您注意到可以使用DOM扩展加载HTML文档。并且XML无效。并输出格式。事情SimpleXMLElement就是做不到。甚至没有肮脏的技巧。
  • 您甚至可能完全切换到DOM扩展,因为至少您知道界面更具差异性并允许您执行操作。您还可以看到学习DOM Level 1的好处,因为您可以在Javascript和其他语言中使用它(对于许多人来说,DOM扩展的巨大好处)。

你可以享受两种扩展的乐趣,我认为你应该知道这两种扩展。越多越好。 PHP中所有基于libxml的扩展都是非常好的和强大的扩展。在{{3}}标签下的Stackoverflow上,有一个很好的传统,可以很好地覆盖这些库,并提供详细的信息。