Skip to content

PHP XML DOM

PHP 提供了内置的扩展来解析和操作 XML 文档。DOM (Document Object Model) 扩展是一个功能强大的选项,它将 XML 文档视为内存中的树形结构。

DOM 解析器将整个 XML 文档加载到内存中,并将其表示为对象(节点)树。这允许对 XML 结构进行复杂的导航、修改和查询。

考虑以下简单的 XML 片段:

<?xml version="1.0" encoding="UTF-8"?>
<message>
<from>Jani</from>
</message>

DOM 解析器将其视为一个层次结构:

  • 文档节点 (Document Node)
  • 元素节点 (Element Node): <message>
  • 文本节点 (Text Node): (<message> 和 <from> 之间的空白符)
  • 元素节点 (Element Node): `<from>`
  • 文本节点 (Text Node): "Jani"
  • 文本节点 (Text Node): (</from> 之后的空白符)

理解这种树形结构是有效使用 DOM API 的关键。

替代方案:对于更简单的 XML 读取任务,特别是处理内存受限的大文件时,SimpleXML 扩展通常提供更易于使用的接口。对于超大文件的流式处理,XMLReader 和 XMLWriter 扩展更适用。

在大多数 PHP 安装中,DOM 扩展(ext-dom)通常默认已编译并启用。通常不需要单独安装。

我们将使用以下 note.xml 文件作为示例:

<?xml version="1.0" encoding="UTF-8"?>
<note importance="high">
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

核心类是 DOMDocument。我们可以将 XML 文件或字符串加载到其中,然后再保存出来。

preserveWhiteSpace = false; $xmlDoc->formatOutput = true; if ($xmlDoc->load('note.xml')) { // 将加载的 XML 保存回字符串 $xmlString = $xmlDoc->saveXML(); // 输出 XML(如果是通过 Web 服务,确保内容类型正确) // header('Content-Type: application/xml; charset=utf-8'); echo htmlspecialchars($xmlString, ENT_QUOTES, 'UTF-8'); } else { echo "Failed to load note.xml"; // 添加适当的错误处理,例如使用 libxml_get_errors() } ?>

此代码创建一个 DOMDocument 对象,将 note.xml 加载到其中(禁用空白符保留并启用输出格式化以提高可读性),然后使用 saveXML() 将文档内容作为字符串输出。

加载后,您可以导航 DOM 树来提取特定数据。

preserveWhiteSpace = false; // 忽略空白文本节点 $xmlDoc->load('note.xml'); // 获取根元素 () $rootElement = $xmlDoc->documentElement; echo "Reading elements directly under :\n"; // 遍历根元素的子节点 foreach ($rootElement->childNodes as $item) { // 检查是否是元素节点(类型 1),以避免文本节点等 if ($item->nodeType === XML_ELEMENT_NODE) { // nodeName 提供标签名(例如 'to') // 元素自身的 nodeValue 通常为 null/空, // 文本内容在其子文本节点中。 // textContent 获取节点及其后代组合的文本内容。 echo $item->nodeName . " = " . $item->textContent . "\n"; } } // 访问属性(例如 元素的 'importance' 属性) if ($rootElement->hasAttribute('importance')) { $importance = $rootElement->getAttribute('importance'); echo "\nImportance attribute: " . htmlspecialchars($importance, ENT_QUOTES, 'UTF-8') . "\n"; } // 使用 getElementsByTagName 查找特定元素 echo "\nFinding all elements:\n"; $bodyElements = $xmlDoc->getElementsByTagName('body'); foreach ($bodyElements as $body) { echo "Body content: " . $body->textContent . "\n"; } ?>

预期输出:

Reading elements directly under : to = Tove from = Jani heading = Reminder body = Don’t forget me this weekend!

Importance attribute: high

Finding all elements: Body content: Don’t forget me this weekend!

解释:

  • documentElement:访问 XML 文档的根元素。
  • childNodes:一个 DOMNodeList,包含所有直接子节点(包括文本节点、注释节点等)。
  • nodeType === XML_ELEMENT_NODE:检查一个节点是否是实际的元素(如 , ),而不是空白符或注释。
  • nodeName:返回元素的标签名。
  • nodeValue:返回节点的值。
  • textContent:返回节点及其所有后代节点的文本内容。
  • getAttribute() / hasAttribute():用于访问元素属性。
  • getElementsByTagName():在上下文节点(或整个文档)中的任何位置查找具有特定标签名的所有元素。

常见陷阱:如果 preserveWhiteSpace 未设置为 false,请注意元素之间的空白符节点。它们会出现在 childNodes 中,可能需要进行显式检查 (nodeType !== XML_TEXT_NODE 或检查 trim($node->nodeValue) 是否为空)。

提示:对于更复杂的查询,特别是大型文档,可以考虑使用 DOMXPath,它允许您使用 XPath 表达式来选择节点。

DOM 扩展提供了更多功能,包括创建新节点、修改现有节点、删除节点以及处理命名空间。有关详细信息,请查阅 DOMDocument、DOMElement、DOMNode、DOMXPath 及相关类的官方 PHP 文档。