如何读取XML元素的命名空间属性?提取Node元素的i:type值
这个问题我之前也踩过坑!因为XML里的i:是命名空间前缀,它对应的实际命名空间URI是http://www.w3.org/2001/XMLSchema-instance,常规的属性访问会忽略命名空间,所以根本拿不到值。下面给你两种PHP里常用的解决方案:
方法一:使用SimpleXML
SimpleXML是PHP里处理XML比较轻量的方式,核心是先注册命名空间,再通过命名空间访问属性:
$xml = '<NodeSet xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://opcfoundation.org/UA/2008/02/Types.xsd"> <Node category="category" i:type="ObjectNode"> <NodeId> <Identifier>i=86</Identifier> </NodeId> </Node> </NodeSet>'; // 加载XML字符串到SimpleXML对象 $sxml = simplexml_load_string($xml); // 注册两个关键命名空间: // 1. 默认的OPC UA命名空间(xmlns=...),起别名ua $sxml->registerXPathNamespace('ua', 'http://opcfoundation.org/UA/2008/02/Types.xsd'); // 2. xsi命名空间(xmlns:i=...),起别名xsi $sxml->registerXPathNamespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance'); // 用XPath定位到<Node>元素 $nodes = $sxml->xpath('//ua:Node'); if (!empty($nodes)) { // 通过命名空间URI获取属性集合 $xsiAttrs = $nodes[0]->attributes('http://www.w3.org/2001/XMLSchema-instance'); // 转换为字符串拿到属性值 $typeValue = (string)$xsiAttrs['type']; echo $typeValue; // 输出:ObjectNode }
方法二:使用DOMDocument + DOMXPath
如果需要更复杂的XML操作,DOMDocument配合XPath会更灵活,同样要先注册命名空间:
$xml = '<NodeSet xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://opcfoundation.org/UA/2008/02/Types.xsd"> <Node category="category" i:type="ObjectNode"> <NodeId> <Identifier>i=86</Identifier> </NodeId> </Node> </NodeSet>'; $dom = new DOMDocument(); // 加载XML,忽略无关的警告(可选) libxml_use_internal_errors(true); $dom->loadXML($xml); libxml_clear_errors(); $xpath = new DOMXPath($dom); // 注册命名空间,和SimpleXML逻辑一致 $xpath->registerNamespace('ua', 'http://opcfoundation.org/UA/2008/02/Types.xsd'); $xpath->registerNamespace('xsi', 'http://www.w3.org/2001/XMLSchema-instance'); // 定位到目标<Node>元素 $nodeElement = $xpath->query('//ua:Node')->item(0); if ($nodeElement) { // 用getAttributeNS方法,传入命名空间URI和属性名(不带前缀) $typeValue = $nodeElement->getAttributeNS('http://www.w3.org/2001/XMLSchema-instance', 'type'); echo $typeValue; // 输出:ObjectNode }
关键注意点
XML的前缀(比如i)只是个“别名”,真正区分命名空间的是它对应的URI。所以不管用哪种方法,都必须通过URI来关联命名空间,而不是直接用前缀访问属性。
内容的提问来源于stack exchange,提问作者salimsaid
相关产品推荐
相关产品推荐

