如何通过PHP读取含多命名空间的XML中的指定值
解决带多命名空间XML的取值问题
嘿,我看你在处理带命名空间的XML取值时遇到了小麻烦,咱们一步步来搞定它~
首先先回顾下你的XML示例:
<?xml version ="1.0"?> <Invoice xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"> <cac:PartyName> <cbc:Name>John Doe</cbc:Name> </cac:PartyName> </Invoice>
还有你写的PHP代码:
<?php $xml = simplexml_load_file('file.xml'); $xml->registerXPathNamespace('cbc', 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2'); $xml->registerXPathNamespace('cac', 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2'); foreach($xml->xpath('//cac:PartyName') as $PartyName) { print_r ($PartyName->xpath('//cbc:Name')); } ?>
问题出在哪?
你当前代码返回整个数组的核心原因是:第二个xpath('//cbc:Name')里的//是全局搜索,它会从XML根节点开始查找所有匹配cbc:Name的元素,而不是在当前$PartyName节点的范围内查找。另外,虽然你注册了cac和cbc的命名空间,但其实还可以更简洁地访问子元素,不用嵌套xpath。
两种修正方案
方案1:修改XPath为相对路径
把全局搜索的//cbc:Name改成相对路径.//cbc:Name,.表示从当前节点开始查找,然后取出第一个匹配的元素并转成字符串:
<?php $xml = simplexml_load_file('file.xml'); $xml->registerXPathNamespace('cbc', 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2'); $xml->registerXPathNamespace('cac', 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2'); foreach($xml->xpath('//cac:PartyName') as $PartyName) { // 用相对路径查找当前节点下的cbc:Name,取第一个结果并转字符串 $name = $PartyName->xpath('.//cbc:Name')[0]; echo (string)$name; // 输出John Doe } ?>
方案2:直接用SimpleXML的对象属性访问
这种方法更简洁,不需要嵌套xpath,直接通过children()方法指定命名空间来访问子元素:
<?php $xml = simplexml_load_file('file.xml'); $xml->registerXPathNamespace('cac', 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2'); foreach($xml->xpath('//cac:PartyName') as $PartyName) { // 直接访问cbc命名空间下的Name元素,转成字符串输出 echo (string)$PartyName->children('cbc', true)->Name; // 输出John Doe } ?>
补充说明
children('cbc', true)里的true表示我们用命名空间的前缀(也就是cbc)来指定,而不是完整的URI,这样代码更简洁。- 如果你后续需要操作根节点(Invoice元素)下的其他默认命名空间元素,还可以注册默认命名空间:
$xml->registerXPathNamespace('ubl', 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2');,之后就可以用//ubl:xxx来搜索默认命名空间的元素了。
内容的提问来源于stack exchange,提问作者user3707281
相关产品推荐
相关产品推荐

