PHP的SimpleXML扩展提供了简洁的接口来解析和操作XML数据,在处理包含属性和命名空间的XML文档时,需要掌握特定的操作方法才能正确读取和修改数据。

处理XML属性
XML元素可以包含多个属性,SimpleXML将元素属性作为对象的动态属性提供,通过数组风格的访问方式即可获取对应属性值。
读取属性
假设我们有如下XML文档,其中book元素包含id属性,author元素包含role属性:
<?xml version="1.0" encoding="UTF-8"?>
<library>
<book id="b001">
<title>PHP编程入门</title>
<author role="main">张三</author>
<price>59.9</price>
</book>
<book id="b002">
<title>XML解析实战</title>
<author role="co">李四</author>
<price>49.9</price>
</book>
</library>
读取属性的示例代码如下:
<?php
$xmlStr = '<?xml version="1.0" encoding="UTF-8"?>
<library>
<book id="b001">
<title>PHP编程入门</title>
<author role="main">张三</author>
<price>59.9</price>
</book>
<book id="b002">
<title>XML解析实战</title>
<author role="co">李四</author>
<price>49.9</price>
</book>
</library>';
$simplexml = simplexml_load_string($xmlStr);
// 读取第一个book元素的id属性
$firstBookId = $simplexml->book[0]['id'];
echo "第一个图书ID:{$firstBookId}n"; // 输出 第一个图书ID:b001
// 读取第一个author元素的role属性
$firstAuthorRole = $simplexml->book[0]->author['role'];
echo "第一个作者角色:{$firstAuthorRole}n"; // 输出 第一个作者角色:main
// 遍历所有book元素的id属性
foreach ($simplexml->book as $book) {
echo "图书ID:{$book['id']},书名:{$book->title}n";
}
// 输出:
// 图书ID:b001,书名:PHP编程入门
// 图书ID:b002,书名:XML解析实战
?>
修改和添加属性
SimpleXML支持直接修改已有属性的值,也可以给元素添加新的属性:
<?php
$xmlStr = '<?xml version="1.0" encoding="UTF-8"?>
<library>
<book id="b001">
<title>PHP编程入门</title>
</book>
</library>';
$simplexml = simplexml_load_string($xmlStr);
// 修改已有属性
$simplexml->book[0]['id'] = 'b001_updated';
// 添加新属性
$simplexml->book[0]->addAttribute('category', '编程');
// 输出修改后的XML
echo $simplexml->asXML();
// 输出结果包含:<book id="b001_updated" category="编程">
?>
处理XML命名空间
当XML文档包含命名空间时,普通的节点访问方式无法获取到带命名空间前缀的节点,需要先注册命名空间再读取。
XML命名空间基础
带命名空间的XML示例如下,其中ns是命名空间前缀,对应命名空间URI为http://ippipp.com/ns:
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:ns="http://ippipp.com/ns">
<ns:user>
<ns:name>王五</ns:name>
<ns:age>25</ns:age>
</ns:user>
<ns:user>
<ns:name>赵六</ns:name>
<ns:age>30</ns:age>
</ns:user>
</root>
注册并读取命名空间节点
使用registerXPathNamespace方法注册命名空间后,结合xpath方法可以读取带命名空间的节点:
<?php
$xmlStr = '<?xml version="1.0" encoding="UTF-8"?>
<root xmlns:ns="http://ippipp.com/ns">
<ns:user>
<ns:name>王五</ns:name>
<ns:age>25</ns:age>
</ns:user>
<ns:user>
<ns:name>赵六</ns:name>
<ns:age>30</ns:age>
</ns:user>
</root>';
$simplexml = simplexml_load_string($xmlStr);
// 注册命名空间,前缀可以自定义,只要和xpath表达式中的一致即可
$simplexml->registerXPathNamespace('myns', 'http://ippipp.com/ns');
// 使用xpath查询所有带命名空间的user节点
$users = $simplexml->xpath('//myns:user');
foreach ($users as $user) {
// 读取命名空间下的子节点,同样需要注册命名空间
$user->registerXPathNamespace('myns', 'http://ippipp.com/ns');
$name = $user->xpath('myns:name')[0];
$age = $user->xpath('myns:age')[0];
echo "姓名:{$name},年龄:{$age}n";
}
// 输出:
// 姓名:王五,年龄:25
// 姓名:赵六,年龄:30
?>
处理默认命名空间
如果XML使用默认命名空间(没有前缀),同样需要注册命名空间后读取:
<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://default.namespace.com">
<user>
<name>孙七</name>
</user>
</root>
<?php
$xmlStr = '<?xml version="1.0" encoding="UTF-8"?>
<root xmlns="http://default.namespace.com">
<user>
<name>孙七</name>
</user>
</root>';
$simplexml = simplexml_load_string($xmlStr);
// 注册默认命名空间,前缀自定义为df
$simplexml->registerXPathNamespace('df', 'http://default.namespace.com');
$users = $simplexml->xpath('//df:user');
foreach ($users as $user) {
$user->registerXPathNamespace('df', 'http://default.namespace.com');
$name = $user->xpath('df:name')[0];
echo "姓名:{$name}n"; // 输出 姓名:孙七
}
?>
注意事项
- 读取属性时如果属性不存在,返回的是
NULL,需要做非空判断避免报错。 - 命名空间的URI必须和XML文档中声明的完全一致,否则无法正确匹配节点。
- 使用
asXML方法可以将修改后的SimpleXML对象转回XML字符串。 - 如果XML文档结构复杂,可以结合
children方法指定命名空间获取子节点,示例:$simplexml->children('http://ippipp.com/ns')。