为什么我的XPath表达式无法匹配XML(SVG)文档中新增的节点?
问题原因
新增的节点没有绑定SVG文档的默认命名空间,导致XPath无法匹配:
- 你使用
XML::LibXML::Element->new('g')创建的是无命名空间的元素,即使将它插入到带有http://www.w3.org/2000/svg默认命名空间的SVG根节点下,DOM结构中该节点的命名空间属性依然为空 - XPath查询
//svg:g只会匹配属于http://www.w3.org/2000/svg命名空间的<g>节点,自然无法匹配到新增的无命名空间节点 - 序列化输出时看起来两个
<g>节点结构一致,是因为XML序列化不会给插入到默认命名空间父节点下的无命名空间子节点显式添加xmlns=""声明,属于视觉上的误导,实际DOM内部的命名空间属性存在差异。
你尝试用svg:g作为节点名创建也无效,是因为创建节点时没有关联前缀对应的命名空间URI,单独写前缀没有实际作用。
解决方法
使用支持命名空间的元素创建方法newNS,明确指定节点所属的命名空间即可:
将原有创建节点的代码
my $layer = XML::LibXML::Element->new('g');
替换为
# 直接指定SVG命名空间URI my $layer = XML::LibXML::Element->newNS('http://www.w3.org/2000/svg', 'g');
如果不想硬编码命名空间URI,也可以从根节点直接读取已有的默认命名空间:
my $root = $svg->documentElement(); # 复用根节点的命名空间 my $layer = XML::LibXML::Element->newNS($root->namespaceURI(), 'g'); $root->appendChild($layer);
修改完成后重新运行代码,XPath查询就可以同时匹配到原有和新增的<g>节点。
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

