Perl中使用XML::LibXML的ends-with函数获取XML标签报错求解决
问题分析与解决:XPath
ends-with函数未找到错误 问题原因
你使用的ends-with()是XPath 2.0及以上版本才支持的函数,但XML::LibXML默认采用XPath 1.0标准,解析器无法识别该函数,因此抛出"function ends-with not found"错误。
解决方法
提供两种可行的修复方案,按需选择:
方法1:用XPath 1.0语法模拟结尾匹配
在XPath 1.0中,可通过substring()与string-length()的组合实现"匹配字符串结尾"的逻辑,替代ends-with():
原错误XPath表达式:
*[ends-with(name(),"stock")]
替换为等效的XPath 1.0表达式:
*[substring(name(), string-length(name()) - string-length('stock') + 1) = 'stock']
修改后的Perl代码片段:
my $stock_value = $branch->findnodes('*[substring(name(), string-length(name()) - string-length("stock") + 1) = "stock"]')->[0]->textContent;
方法2:用Perl代码直接过滤节点
跳过XPath的字符串匹配逻辑,直接遍历branch下的子节点,用Perl原生的正则匹配判断节点名是否以stock结尾,这种方式更直观且不依赖XPath版本:
完整修改后的代码:
use warnings; use strict; use feature 'say'; use Data::Dumper; use XML::LibXML; my $file = "ex.xml"; my $parser = XML::LibXML->load_xml(location => $file); my %branch_stock; foreach my $sec ($parser->findnodes('/Details/Info')) { for my $branch ($sec->findnodes('./branch')) { my $branch_name = $branch->getAttribute('name'); # 遍历当前branch下的所有子节点 foreach my $node ($branch->findnodes('*')) { my $node_name = $node->nodeName; # 正则匹配节点名是否以stock结尾 if ($node_name =~ /stock$/) { $branch_stock{$branch_name} = $node->textContent; last; # 找到目标节点后退出循环,避免重复匹配 } } } } say Dumper \%branch_stock;
测试结果
两种方法均可正确提取每个branch下的stock相关值,最终输出的哈希结构为:
$VAR1 = { 'city_1' => '10000', 'city_2' => '2000', 'city_3' => '3000' };
内容的提问来源于stack exchange,提问作者Perl_Newbie
相关产品推荐
相关产品推荐

