Skip to content

PHP SimpleXML 解析器

SimpleXML 是 PHP 的一个扩展,它提供了一个直观且易于使用的接口,用于解析和操作 XML 数据。

SimpleXML 最适合处理结构简单、类似记录的 XML 数据。它将 XML 文档表示为一个对象,允许你使用标准的对象属性和数组索引表示法访问元素和属性。

主要特性:

  • 树状结构: 将整个 XML 文档解析到内存中的树状结构。
  • 易于访问: 提供简单的语法(如 $xml->element 或 $xml['attribute'])来导航和检索数据,前提是你了解 XML 结构。
  • 迭代: 允许使用循环(如 foreach)轻松迭代具有相同名称的元素。
  • 简洁: 与 DOM 或 Expat 解析器相比,读取简单的 XML 数据通常需要更少的代码。

SimpleXML 扩展是 PHP 核心的一部分,在现代 PHP 安装中默认启用。无需单独安装。

函数 simplexml_load_string() 用于解析存储在 PHP 字符串变量中的 XML 数据。

考虑存储在字符串中的以下 XML 数据:

<?php
$myXMLData = <<<XML
<?xml version='1.0' encoding='UTF-8'?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
XML;
?>

以下是使用 simplexml_load_string() 解析它的方法:

<?php
$myXMLData = <<<XML
<?xml version='1.0' encoding='UTF-8'?>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
XML;
// 处理可能不受信的 XML 时,为了安全至关重要,
// 可防止 XXE 攻击。在加载之前禁用。
libxml_disable_entity_loader(true);
$xml = simplexml_load_string($myXMLData);
if ($xml === false) {
echo "Failed loading XML string.<br>";
// 可选:显示特定错误(参见下面的错误处理示例)
foreach(libxml_get_errors() as $error) {
echo htmlspecialchars($error->message), "<br>";
}
exit;
}
// 将元素作为对象属性访问
echo "To: " . htmlspecialchars($xml->to) . "<br>";
echo "From: " . htmlspecialchars($xml->from) . "<br>";
echo "Heading: " . htmlspecialchars($xml->heading) . "<br>
echo "Body: " . htmlspecialchars($xml->body) . "<br>";
// 用于调试:查看结构
// echo "<pre>";
// print_r($xml);
// echo "</pre>";
?>

上面代码的输出:

To: Tove
From: Jani
Heading: Reminder
Body: Don’t forget me this weekend!

SimpleXML 依赖于底层的 libxml 库。为了正确处理 XML 解析错误,请使用 libxml 错误处理函数:

<?php
// 启用 libxml 用户错误处理
libxml_use_internal_errors(true);
// 禁用外部实体加载以提高安全性
libxml_disable_entity_loader(true);
$brokenXMLData =
"<?xml version='1.0' encoding='UTF-8'?>
<document>
<user>John Doe</wronguser>
<email>john@example.com</wrongemail>
</document>";
$xml = simplexml_load_string($brokenXMLData);
if ($xml === false) {
echo "**Failed loading XML:**<br>";
$errors = libxml_get_errors();
foreach ($errors as $error) {
// 显示错误详情 (级别、代码、消息、文件、行、列)
echo " - Level ". htmlspecialchars($error->level) .": " . htmlspecialchars(trim($error->message)) . " on line " . htmlspecialchars($error->line) ."<br>";
}
// 处理后清除错误缓冲区
libxml_clear_errors();
} else {
echo "XML loaded successfully (though it might have non-fatal issues if not fully checked).";
// 在此处处理 $xml 对象...
// print_r($xml);
}
// 如果脚本后面需要,可以选择恢复默认错误处理
// libxml_use_internal_errors(false);
?>

损坏 XML 的输出:

Failed loading XML:

  • Level 3: Opening and ending tag mismatch: user line 3 and wronguser on line 3
  • Level 3: Opening and ending tag mismatch: email line 4 and wrongemail on line 4

安全注意: 从不受信的源(包括外部文件或用户输入)加载 XML 之前,请务必使用 libxml_disable_entity_loader(true);,以防止 XML 外部实体 (XXE) 漏洞。

函数 simplexml_load_file() 直接从文件路径或 URL 解析 XML 数据。

假设我们有一个名为 note.xml 的 XML 文件,内容如下:

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

以下示例演示如何解析此文件:

<?php
// 启用用户错误处理并禁用实体加载器
libxml_use_internal_errors(true);
libxml_disable_entity_loader(true);
$xmlFile = 'note.xml';
if (!file_exists($xmlFile)) {
die("Error: File not found ($xmlFile)");
}
$xml = simplexml_load_file($xmlFile);
if ($xml === false) {
echo "Failed loading XML file: $xmlFile<br>";
foreach(libxml_get_errors() as $error) {
echo htmlspecialchars(trim($error->message)), "<br>";
}
libxml_clear_errors();
exit;
}
// 像之前一样访问数据
echo "To: " . htmlspecialchars($xml->to) . "<br>";
echo "From: " . htmlspecialchars($xml->from) . "<br>";
// ... 等等
// 访问属性的示例(如果存在,例如 <note id="123">)
// echo "Note ID: " . htmlspecialchars($xml['id']) . "<br>";
?>

输出(假设 note.xml 存在且有效)将类似于从字符串读取的示例。

提示:后续章节将深入探讨如何使用 SimpleXML 访问特定节点值、属性以及处理更复杂的 XML 结构。

有关 SimpleXML 函数的完整列表和更多详细示例,请参阅官方 PHP 文档或专门的 SimpleXML 教程。