我不太理解为什么 PHP 需要两个 XML 解析器。
能有人解释一下这两者之间的区别吗?
我不太理解为什么 PHP 需要两个 XML 解析器。
能有人解释一下这两者之间的区别吗?
顺便说一句,不是只有两个解析器,而是PHP中还有几个解析器。SimpleXml和DOM只是将文档解析为树结构的两个解析器。其他的解析器/读取器/写入器要么是拉取式的,要么是事件驱动的。
还可以看看我的回答
我将尽可能提供最简短的答案,以便初学者能够轻松理解。为了简洁起见,我也略微简化了一些内容。请跳到答案结尾查看过度简化的 TL;DR 版本。
DOM和SimpleXML实际上不是两个不同的解析器。真正的解析器是libxml2,它被DOM和SimpleXML内部使用。因此,DOM/SimpleXML只是使用相同解析器的两种方式,并提供将一个对象转换为另一个对象的方法。
SimpleXML旨在非常简单,因此它具有一小组功能,并专注于读取和写入数据。也就是说,您可以轻松地读取或写入XML文件,可以更新某些值或删除某些节点(有一些限制!),就这样。没有花哨的操作,您无法访问较不常见的节点类型。例如,SimpleXML无法创建CDATA节,尽管它可以读取它们。
DOM 提供了一个完整的 DOM 实现,以及一些非标准方法,如 appendXML。如果您习惯于在 Javascript 中操作 DOM,则会在 PHP 的 DOM 中找到完全相同的方法。基本上可以做任何事情,甚至处理 HTML。这种功能丰富性的反面是它比 SimpleXML 更加复杂和冗长。
人们经常想知道/询问应该使用什么扩展来处理他们的XML或HTML内容。实际上选择很容易,因为一开始就没有太多选择:
simplexml_import_dom
和SimpleXML遍历它,因此并不完全需要使用DOM。 - IMSoP这两个库之间最大的区别在于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解析器在加载文档时都可以展开CDATA节点。当使用LIBXML_NOCDATA
选项与simplexml_load_*
函数或构造函数一起使用时,SimpleXML会展开这些节点。(该选项也适用于DOMDocument::loadXML()
)SimpleXMLElement
还将访问子元素和属性列表进行了抽象,并通过元素名称(属性访问)、属性(数组访问)提供遍历,以及通过 children()
和 attributes()
方法提供命名空间访问,同时还是一个 Traversable
,可以迭代其“自己”的子元素(元素或属性)。DOM遵循DOMDocument Core Level 1规范。您可以使用该接口处理几乎所有想象得到的XML。但是它仅适用于Level 1,因此与现代DOMDocument Levels(如3)相比,在某些更酷的功能方面受到限制。当然,SimpleXML也在这里失去了优势。
SimpleXMLElement允许转换为子类型。这在PHP中非常特殊。DOM也允许这样做,尽管需要更多的工作并选择更具体的节点类型。
XPath 1.0被两者都支持,SimpleXML的结果是SimpleXMLElements
的array
,而DOM是DOMNodelist
。
SimpleXMLElement
支持转换为字符串和数组(json),而DOM中的DOMNode类则不支持。它们提供将其转换为数组的功能,但仅像任何其他对象一样(公共属性作为键/值对)。
SimpleXMLElement
导入DOM中,反之亦然。您学习更多关于DOM的知识,并使用扩展来完成一些使用SimpleXMLElement
无法完成(或者无法找到如何完成)的工作。__toString()
时,CDATA 节点始终以与文本节点相同的方式合并;LIBXML_NOCDATA
选项只有在“重新序列化”对象时才会有所区别——无论是使用 ->asXML()
还是输出整个结构体使用 print_r()
、json_encode()
等。 - IMSoPjson_encode()
函数所困扰,因为您将其排除在外,我包含它(间接)因为涉及到数组转换。 - hakre正如其他人所指出的,DOM和SimpleXML扩展并不严格意义上是"XML解析器",而是底层libxml2解析器生成的结构的不同接口。
SimpleXML接口将XML视为序列化数据结构,就像您处理解码后的JSON字符串一样。因此,它提供了快速访问文档内容的方式,重点是通过名称访问元素,并读取它们的属性和文本内容(包括自动折叠实体和CDATA节)。它支持包含多个命名空间的文档(主要使用children()
和attributes()
方法),并可以使用XPath表达式搜索文档。它还包括对内容的基本操作支持-例如使用新字符串添加或覆盖元素或属性。
这两个接口都需要将完整文档解析到内存中,并有效地将指针包装到已解析的表示中;您甚至可以使用 simplexml_import_dom()
和 dom_import_simplexml()
在两个包装器之间进行切换,例如使用 DOM API 中的函数向 SimpleXML 添加“缺失”功能。对于较大的文档,“基于拉取”的 XMLReader 或“基于事件”的 XML Parser 可能更合适。
SimpleXML是一个简单的XML内容解析器,仅限于解析XML格式内容。你无法解析标准的HTML内容。它易于使用且快速,因此非常适用于创建简单的应用程序。
DOM扩展则更加强大。它使您能够解析几乎任何DOM文档,包括HTML、XHTML和XML。它使您能够打开、编写甚至纠正输出代码,支持XPath和更多操作。因此,它的使用更加复杂,因为该库相当复杂,这使得它成为处理大型数据操作的完美工具。
希望回答了您的问题 :)
XMLReader
http://php.net/xmlreader ;) 它更快,消耗的内存不那么多(它是基于流的),但使用起来更加困难。--刚刚读到你的回答的结尾:你提到了它。^^ - KingCrunch$attrs = $sxe->xpath('/foo/bar/@baz'); echo $attrs[0];
- Josh Davisprint_r
或var_dump
)的一个限制,并不是对象本身 - 尽管我认为这仍然是该库的一个限制。 - IMSoP