如何访问带命名空间的XML节点属性?SimpleXMLElement遇NULL问题
问题描述
我有一段XML数据:
<?xml version="1.0" encoding="UTF-8"?> <ns1:catalog xmlns:ns1="http://www.omnichannelintegrationlayer.com/xml/catalog/2016-01-01" catalog-id="at-master-catalog"> <ns1:product product-id="4132002004"> <ns1:min-order-quantity>1</ns1:min-order-quantity> <ns1:step-quantity>1</ns1:step-quantity> <ns1:short-description xmlns:ns2="xml" ns2:lang="de-AT">Jogginghose Cacy jr </ns1:short-description> <ns1:short-description xmlns:ns2="xml" ns2:lang="de-CH">Jogginghose Cacy jr </ns1:short-description> </ns1:product> </ns1:catalog>
我想要根据ns2:lang属性筛选short-description节点,目前编写了如下PHP代码:
foreach ($xml->xpath("//ns1:product[@product-id='".$productid."']/ns1:short-description/") as $short_description) { $namespaces = $short_description->getNameSpaces(true); $ns1 = $short_description->children($namespaces['ns1']); $ns2 = $short_description->children($namespaces['ns2']); var_dump($ns2); echo $ns2["lang"]; }
var_dump输出显示属性存在:
object(SimpleXMLElement)#27 (1) { ["@attributes"]=> array(1) { ["lang"]=> string(5) "de-AT" } }
但使用$ns2["lang"]获取时返回NULL,尝试过声明命名空间等方法仍无法解决,恳请帮助。
解决方案
问题出在你对SimpleXML处理命名空间属性的方式理解有误:ns2是属性的命名空间,不是子节点的命名空间,所以不能用children()方法来获取,而是需要用attributes()方法指定命名空间来读取属性。
方法1:直接用attributes()获取带命名空间的属性
修改你的代码,把获取ns2属性的部分换成attributes()方法:
foreach ($xml->xpath("//ns1:product[@product-id='".$productid."']/ns1:short-description") as $short_description) { $namespaces = $short_description->getNameSpaces(true); // 获取ns2命名空间下的属性 $ns2Attrs = $short_description->attributes($namespaces['ns2']); // 读取lang属性 $lang = $ns2Attrs['lang']; var_dump($lang); // 会输出string(5) "de-AT" 或 string(5) "de-CH" echo $lang; }
方法2:在XPath中直接筛选指定lang属性的节点
如果你的目标是直接筛选出特定lang的short-description,可以在XPath查询里直接指定,这样更高效:
// 先注册命名空间,避免XPath里的前缀问题 $xml->registerXPathNamespace('ns1', 'http://www.omnichannelintegrationlayer.com/xml/catalog/2016-01-01'); $xml->registerXPathNamespace('ns2', 'xml'); // 直接筛选lang为de-AT的节点 $targetNodes = $xml->xpath("//ns1:product[@product-id='".$productid."']/ns1:short-description[@ns2:lang='de-AT']"); foreach ($targetNodes as $node) { echo $node; // 输出对应的描述文本 }
为什么原来的代码不行?
$short_description->children($namespaces['ns2'])是在找short-description节点下属于ns2命名空间的子节点,但你的XML里ns2:lang是short-description自身的属性,不是子节点,所以这个调用返回的对象虽然包含了属性(因为SimpleXML的特性),但用数组方式访问时无法正确获取,必须用attributes()方法明确指定命名空间来读取属性。
内容的提问来源于stack exchange,提问作者rapidoodle
相关产品推荐
相关产品推荐

