XML 处理:从 XPath 查询到 DOM 操作的全面指南
1. XPath 查询基础
XPath 是一种强大的 XML 查询语言,能够帮助我们在 XML 文档中精准定位元素。例如,使用查询 “
/name” 可以匹配所有
<name>
元素,而不管它是包含在
<dog>
还是
<cat>
元素中。若要获取当前
SimpleXMLElement
的父元素,可以使用查询 “..” 或者 “parent::
“。
以下是一个简单的示例代码:
<?php
error_reporting(E_ALL);
$xml = simplexml_load_file("template.xhtml");
$content = $xml->xpath("//*[@id='main_center']");
print (String)$content[0];
?>
在这个例子中,我们使用查询 “//*[@id=’main_center’]” 来查找属性
id
等于 ‘main_center’ 的元素。在 XPath 中,使用
@
符号来匹配属性。
2. XML 命名空间
XML 命名空间用于定义元素所属的集合,避免数据歧义。当存在不同类型的节点包含相同名称的元素时,命名空间就显得尤为重要。例如,我们可以为猫和狗定义不同的命名空间,确保它们的内部元素具有唯一的名称。
以下是一个使用命名空间的示例:
<?php
error_reporting(E_ALL ^ E_NOTICE);
$xml = <<<THE_XML
<animals xmlns:dog="http://foobar.com/dog" xmlns:cat="http://foobar.com/cat" >
<dog:name>snoopy</dog:name>
<dog:color>brown</dog:color>
<dog:breed>beagle cross</dog:breed>
<cat:name>teddy</cat:name>
<cat:color>brown</cat:color>
<cat:breed>tabby</cat:breed>
<dog:name>jade</dog:name>
<dog:color>black</dog:color>
<dog:breed>lab cross</dog:breed>
</animals>
THE_XML;
$xml_object = simplexml_load_string($xml);
$xml_object->registerXPathNamespace('cat', 'http://foobar.com/cat');
$xml_object->registerXPathNamespace('dog', 'http://foobar.com/dog');
$names = $xml_object->xpath("dog:name");
foreach ($names as $name) {
print $name . "<br/>";
}
?>
在运行 XPath 查询之前,我们需要先注册命名空间。注册后,在查询元素时需要为其添加命名空间前缀。
3. 根据元素值匹配元素并读取属性值
使用 XPath 的
contains
函数可以根据元素值匹配元素,然后读取该元素的属性值。
<?php
error_reporting(E_ALL);
$xml = <<<THE_XML
<animals>
<dog>
<name id="1">snoopy</name>
<color>brown</color>
<breed>beagle cross</breed>
</dog>
<cat>
<name id="2">teddy</name>
<color>brown</color>
<breed>tabby</breed>
</cat>
<dog>
<name id="3">jade</name>
<color>black</color>
<breed>lab cross</breed>
</dog>
</animals>
THE_XML;
$xml_object = simplexml_load_string($xml);
$result = $xml_object->xpath("dog/name[contains(., 'jade')]");
print (String)$result[0]->attributes()->id;
?>
contains
函数接受两个参数,第一个参数表示搜索的位置(
.
表示当前节点),第二个参数是搜索字符串。
4. RSS 解析
RSS(Really Simple Syndication)是一种用于发布和订阅内容的简单方法。以《连线》杂志的 RSS 订阅源为例,我们可以使用 XML 知识轻松解析其内容。
<table>
<tr><th>Story</th><th>Date</th><th>Creator</th></tr>
<?php
error_reporting(E_ALL);
$xml = simplexml_load_file("http://feeds.wired.com/wired/index?format=xml");
foreach($xml->channel->item as $item){
print "<tr><td><a href='".$item->link."'>".$item->title."</a></td>";
print "<td>".$item->pubDate."</td>";
$creator_by_xpath = $item->xpath("dc:creator");
print "<td>".(String)$creator_by_xpath[0]."</td></tr>";
//equivalent creator, using children function instead of xpath function
//$creator_by_namespace = $item->children('http://purl.org/dc/elements/1.1/')->creator;
//print "<td>".(String)$creator_by_namespace[0]."</td></tr>";
}
?>
</table>
在这个示例中,我们创建了一个包含文章标题、发布日期和创作者的表格。注意,在 XML 中,创作者元素位于命名空间中,因此我们使用 XPath 来获取它。
5. 使用 SimpleXML 生成 XML 文档
我们可以使用
SimpleXML
从数组、对象或数据库等数据形式生成 XML 文档。以下是一个基本的示例:
<?php
error_reporting(E_ALL ^ E_NOTICE);
//generate the xml, starting with the root
$animals = new SimpleXMLElement('<animals/>');
$animals->{0} = 'Hello World';
$animals->asXML('animals.xml');
//verify no errors with our newly created output file
var_dump(simplexml_load_file('animals.xml'));
?>
这个示例创建了一个根元素
<animals>
,并为其赋值,然后将其保存到文件中。为了验证操作是否成功,我们加载保存的文件并输出其内容。
6. 从数组数据生成 XML 文档
当我们有动物数据以数组形式存储时,可以使用
SimpleXML
将其转换为 XML 文档。
<?php
error_reporting(E_ALL ^ E_NOTICE);
//our data, stored in arrays
$dogs_array = array(
array("name" => "snoopy",
"color" => "brown",
"breed" => "beagle cross"
),
array("name" => "jade",
"color" => "black",
"breed" => "lab cross"
),
);
$cats_array = array(
array("name" => "teddy",
"color" => "brown",
"breed" => "tabby"
),
);
//generate the xml, starting with the root
$animals = new SimpleXMLElement('<animals/>');
$cats_xml = $animals->addChild('cats');
$dogs_xml = $animals->addChild('dogs');
foreach ($cats_array as $c) {
$cat = $cats_xml->addChild('cat');
foreach ($c as $key => $value) {
$tmp = $cat->addChild($key);
$tmp->{0} = $value;
}
}
foreach ($dogs_array as $d) {
$dog = $dogs_xml->addChild('dog');
foreach ($d as $key => $value) {
$tmp = $dog->addChild($key);
$tmp->{0} = $value;
}
}
var_dump($animals);
$animals->asXML('animals.xml');
print '<br/><br/>';
//verify no errors with our newly created output file
var_dump(simplexml_load_file('animals.xml'));
?>
通过不断调用
addChild
方法,我们可以创建一个完整的节点树。不过,
asXML()
方法输出的内容格式不太美观,我们可以使用
DOMDocument
类来解决这个问题。
graph TD;
A[开始] --> B[创建 SimpleXMLElement 根元素];
B --> C[添加子元素];
C --> D[保存为 XML 文件];
D --> E[验证文件是否正确];
E --> F[结束];
7. 使用 DOMDocument 格式化 XML 输出
为了让 XML 输出格式更美观,我们可以使用
DOMDocument
类。
$animals_dom = new DOMDocument('1.0');
$animals_dom->preserveWhiteSpace = false;
$animals_dom->formatOutput = true;
//returns a DOMElement
$animals_dom_xml = dom_import_simplexml($animals);
$animals_dom_xml = $animals_dom->importNode($animals_dom_xml, true);
$animals_dom_xml = $animals_dom->appendChild($animals_dom_xml);
$animals_dom->save('animals_formatted.xml');
这段代码创建了一个新的
DOMDocument
对象,并设置其格式化输出。然后将
SimpleXMLElement
对象导入到新的
DOMElement
对象中,最后将格式化后的输出保存到文件中。
8. DOMDocument 概述
除了
SimpleXML
,
DOMDocument
也是 PHP 中常用的 XML 处理扩展。它比
SimpleXML
更强大,但使用起来相对复杂一些。
DOMDocument
具有以下特点:
- 遵循 W3C DOM API,熟悉 JavaScript DOM 的开发者容易上手。
- 支持 HTML 解析。
- 具有不同的节点类型,提供更多的控制。
- 可以将原始 XML 追加到现有 XML 文档中。
- 更易于通过更新或删除节点来修改现有文档。
- 对 CDATA 和注释提供更好的支持。
9. DOMDocument 的使用
DOMDocument
可以从字符串、文件或
SimpleXML
对象加载 XML。
//creating a DOMDocument object
$dom_xml = new DOMDocument();
//from a string
$dom_xml->loadXML('the full xml string');
// from a file
$dom_xml->load('animals.xml');
// imported from a SimpleXML object
$dom_element = dom_import_simplexml($simplexml);
$dom_element = $dom_xml->importNode($dom_element, true);
$dom_element = $dom_xml->appendChild($dom_element);
要在
DOM
对象中导航,可以使用面向对象的函数调用,如
$dom_xml->item(0)->firstChild->nodeValue
、
$dom_xml->childNodes
等。此外,
DOMDocument
还提供了多个保存函数,如
save
、
saveHTML
、
saveHTMLFile
和
saveXML
,以及
validate
函数来检查文档的合法性。
10. 使用 DOM 进行元素查找和属性值搜索
以下是使用
DOM
进行元素查找和属性值搜索的示例:
<?php
error_reporting(E_ALL ^ E_NOTICE);
$xml = <<<THE_XML
<animals>
<dog>
<name>snoopy</name>
<color>brown</color>
<breed>beagle cross</breed>
</dog>
<cat>
<name>teddy</name>
<color>brown</color>
<breed>tabby</breed>
</cat>
<dog>
<name>jade</name>
<color>black</color>
<breed>lab cross</breed>
</dog>
</animals>
THE_XML;
$xml_object = new DOMDocument();
$xml_object->loadXML($xml);
$xpath = new DOMXPath($xml_object);
$names = $xpath->query("*/name");
foreach ($names as $element) {
$parent_type = $element->parentNode->nodeName;
echo "$element->nodeValue ($parent_type)<br/>";
}
?>
<?php
error_reporting(E_ALL);
$xml = <<<THE_XML
<animals>
<dog>
<name id="1">snoopy</name>
<color>brown</color>
<breed>beagle cross</breed>
</dog>
<cat>
<name id="2">teddy</name>
<color>brown</color>
<breed>tabby</breed>
</cat>
<dog>
<name id="3">jade</name>
<color>black</color>
<breed>lab cross</breed>
</dog>
</animals>
THE_XML;
$xml_object = new DOMDocument();
$xml_object->loadXML($xml);
$xpath = new DOMXPath($xml_object);
// 后续代码可根据具体需求补充
?>
在这些示例中,我们展示了如何使用
DOM
进行元素查找和属性值搜索。与
SimpleXML
不同,
DOM
需要创建
DOMXPath
对象并调用其
query
方法。
通过以上内容,我们全面介绍了 XML 处理的各个方面,包括 XPath 查询、命名空间使用、RSS 解析、
SimpleXML
生成 XML 文档以及
DOMDocument
的使用等。希望这些知识能帮助你更好地处理 XML 数据。
XML 处理:从 XPath 查询到 DOM 操作的全面指南
11. DOMDocument 与 SimpleXML 的对比
为了更清晰地展示
DOMDocument
和
SimpleXML
的差异,我们来详细对比一下它们的特点和使用场景。
| 特性 | SimpleXML | DOMDocument |
|---|---|---|
| 易用性 | 简单直接,适合快速开发和简单的 XML 处理任务 | 相对复杂,需要更多的代码和步骤,但功能更强大 |
| 节点类型 | 所有节点使用相同的底层对象,缺乏明确的节点类型区分 |
具有不同的节点类型,如
XML_ELEMENT_NODE
、
XML_ATTRIBUTE_NODE
和
XML_TEXT_NODE
,提供更精细的控制
|
| 输出格式化 |
asXML()
方法输出的内容格式不美观,通常为单行
|
可以通过设置
preserveWhiteSpace
和
formatOutput
属性来实现漂亮的格式化输出
|
| 遵循标准 | 无特定标准遵循 | 遵循 W3C DOM API,对于熟悉 JavaScript DOM 的开发者更友好 |
| 功能扩展性 | 功能相对有限,主要用于基本的 XML 解析和生成 | 支持 HTML 解析、追加原始 XML、修改现有文档等更多高级功能 |
12. 处理 XML 文档中的命名空间(DOMDocument 方式)
在使用
DOMDocument
处理包含命名空间的 XML 文档时,我们需要进行一些额外的操作。以下是一个示例:
<?php
error_reporting(E_ALL ^ E_NOTICE);
$xml = <<<THE_XML
<animals xmlns:dog="http://foobar.com/dog" xmlns:cat="http://foobar.com/cat" >
<dog:name>snoopy</dog:name>
<dog:color>brown</dog:color>
<dog:breed>beagle cross</dog:breed>
<cat:name>teddy</cat:name>
<cat:color>brown</cat:color>
<cat:breed>tabby</cat:breed>
<dog:name>jade</dog:name>
<dog:color>black</dog:color>
<dog:breed>lab cross</dog:breed>
</animals>
THE_XML;
$dom_xml = new DOMDocument();
$dom_xml->loadXML($xml);
$xpath = new DOMXPath($dom_xml);
$xpath->registerNamespace('dog', 'http://foobar.com/dog');
$xpath->registerNamespace('cat', 'http://foobar.com/cat');
$names = $xpath->query('dog:name');
foreach ($names as $name) {
echo $name->textContent . '<br/>';
}
?>
在这个示例中,我们首先创建了一个
DOMDocument
对象并加载 XML 字符串。然后,我们创建了一个
DOMXPath
对象,并使用
registerNamespace
方法注册命名空间。最后,我们使用
query
方法执行 XPath 查询,并遍历结果输出狗的名字。
13. 修改现有 XML 文档(DOMDocument 方式)
DOMDocument
提供了强大的功能来修改现有 XML 文档。以下是一个示例,展示如何更新节点的值和删除节点:
<?php
error_reporting(E_ALL);
$xml = <<<THE_XML
<animals>
<dog>
<name id="1">snoopy</name>
<color>brown</color>
<breed>beagle cross</breed>
</dog>
<cat>
<name id="2">teddy</name>
<color>brown</color>
<breed>tabby</breed>
</cat>
<dog>
<name id="3">jade</name>
<color>black</color>
<breed>lab cross</breed>
</dog>
</animals>
THE_XML;
$dom_xml = new DOMDocument();
$dom_xml->loadXML($xml);
// 更新节点的值
$name_nodes = $dom_xml->getElementsByTagName('name');
foreach ($name_nodes as $name_node) {
if ($name_node->textContent == 'snoopy') {
$name_node->textContent = 'Snoopy the Hero';
}
}
// 删除节点
$cat_node = $dom_xml->getElementsByTagName('cat')->item(0);
if ($cat_node) {
$cat_node->parentNode->removeChild($cat_node);
}
// 保存修改后的 XML
$dom_xml->save('modified_animals.xml');
?>
在这个示例中,我们首先加载 XML 字符串到
DOMDocument
对象中。然后,我们使用
getElementsByTagName
方法获取所有
<name>
节点,并更新名为 ‘snoopy’ 的节点的值。接着,我们删除了第一个
<cat>
节点。最后,我们使用
save
方法将修改后的 XML 保存到文件中。
14. 处理 XML 文档中的 CDATA 和注释(DOMDocument 方式)
DOMDocument
对 CDATA 和注释提供了很好的支持。以下是一个示例:
<?php
error_reporting(E_ALL ^ E_NOTICE);
$dom_xml = new DOMDocument();
$root = $dom_xml->createElement('root');
$dom_xml->appendChild($root);
// 添加 CDATA 节点
$cdata = $dom_xml->createCDATASection('This is a CDATA section with special characters <>&');
$root->appendChild($cdata);
// 添加注释节点
$comment = $dom_xml->createComment('This is a comment');
$root->appendChild($comment);
// 保存 XML
$dom_xml->save('cdata_comment.xml');
?>
在这个示例中,我们创建了一个
DOMDocument
对象,并添加了一个根元素。然后,我们使用
createCDATASection
方法创建了一个 CDATA 节点,并使用
createComment
方法创建了一个注释节点。最后,我们将这些节点添加到根元素中,并将 XML 保存到文件中。
15. 总结与最佳实践
通过以上对 XML 处理的各个方面的介绍,我们可以总结出一些最佳实践:
-
简单任务优先选择 SimpleXML
:如果你的 XML 处理任务比较简单,如快速解析或生成基本的 XML 文档,
SimpleXML
是一个不错的选择,它的代码简洁,易于上手。
-
复杂任务使用 DOMDocument
:对于需要处理复杂 XML 结构、进行精细控制、修改现有文档或处理命名空间等高级任务,
DOMDocument
更适合,虽然它的使用相对复杂,但功能强大。
-
合理使用 XPath
:XPath 是 XML 查询的强大工具,无论是
SimpleXML
还是
DOMDocument
都支持 XPath 查询。在编写 XPath 查询时,要注意命名空间的处理,确保查询的准确性。
-
注意输出格式化
:如果需要美观的 XML 输出,使用
DOMDocument
的
formatOutput
属性进行格式化。
-
错误处理
:在处理 XML 时,要注意错误处理,确保代码的健壮性。可以使用
error_reporting
函数来控制错误信息的显示。
graph LR;
A[选择处理方式] -->|简单任务| B[SimpleXML];
A -->|复杂任务| C[DOMDocument];
B --> D[快速解析/生成 XML];
C --> E[处理命名空间];
C --> F[修改现有文档];
C --> G[处理 CDATA 和注释];
D --> H[完成任务];
E --> H;
F --> H;
G --> H;
通过遵循这些最佳实践,你可以更高效地处理 XML 数据,避免常见的错误和问题。希望这些内容对你在 XML 处理方面有所帮助,让你能够更加熟练地运用相关技术来解决实际问题。
超级会员免费看
58

被折叠的 条评论
为什么被折叠?



