我无法理解为什么我们在PHP中需要2个XML解析器。
有人可以解释这两者之间的区别吗?
答案 0 :(得分:96)
简而言之:
SimpleXml
$root->foo->bar['attribute']
DOM
这两个都基于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内容。实际上选择很容易,因为开始时没有太多选择:
答案 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)
两个库之间最大的区别是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
option与simplexml_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也允许这样做,虽然它需要更多的工作,并且需要选择更具体的节点类型。
两者都支持 php,SimpleXML中的结果是array
SimpleXMLElements
,在DOM中DOMNodelist
。
SimpleXMLElement
支持转换为字符串和数组(json),DOM中的DOMNode类不支持。它们提供了转换为数组,但是只像其他任何对象一样(公共属性作为键/值)。
SimpleXMLElement
导入DOM,反之亦然。您可以了解有关DOM的更多信息以及如何使用扩展来执行您无法(或无法了解如何)处理SimpleXMLElement
的内容。你可以享受两种扩展的乐趣,我认为你应该知道这两种扩展。越多越好。 PHP中所有基于libxml的扩展都是非常好的和强大的扩展。在{{3}}标签下的Stackoverflow上,有一个很好的传统,可以很好地覆盖这些库,并提供详细的信息。