Perl:无法使用 Twig::XPath 语法提取同级值
Perl: unable to extract sibling value using Twig::XPath syntax
最近我开始使用 XML::Twig::XPath 但该模块似乎无法识别 xpath 语法。
在下面XML中,如果PlcAndNm节点的值为"ext_1"
,我想要"Txt"节点的值
<?xml version="1.0" encoding="UTF-8"?>
<root>
<Document>
<RedOrdrV03>
<MsgId>
<Id>1</Id>
</MsgId>
<Xtnsn>
<PlcAndNm>ext_1</PlcAndNm>
<Txt>1234</Txt>
</Xtnsn>
<Xtnsn>
<PlcAndNm>ext_2</PlcAndNm>
<Txt>ABC</Txt>
</Xtnsn>
</RedOrdrV03>
</Document>
<Document>
<RedOrdrV03>
<MsgId>
<Id>2</Id>
</MsgId>
<Xtnsn>
<PlcAndNm>ext_1</PlcAndNm>
<Txt>9876</Txt>
</Xtnsn>
<Xtnsn>
<PlcAndNm>ext_2</PlcAndNm>
<Txt>DEF</Txt>
</Xtnsn>
</RedOrdrV03>
</Document>
</root>
我已经尝试过 whit 表达式 //Xtnsn[PlcAndNm="ext_1"]/Txt 但我收到了一个错误
这是代码:
use XML::Twig::XPath;
my $subelt_count = 1;
my @processed_elements;
my $xmlfile = 'c:/test_file.xml';
my $parser = XML::Twig->new(
twig_roots => { 'RedOrdrV03' => \&process_xml } ,
end_tag_handlers => { 'Document' },
);
$parser->parsefile($xmlfile);
sub process_xml {
my ( $twig, $elt ) = @_;
push( @processed_elements, $elt );
if ( @processed_elements >= $subelt_count ) {
my $MsgId = $twig->findvalue('RedOrdrV03/MsgId/Id');
my $Xtnsn_Txt1 = $twig->findvalue('//Xtnsn[PlcAndNm="ext_1"]/Txt');
print "MsgId: $MsgId - Xtnsn_Txt1: $Xtnsn_Txt1\n";
}
$_->delete for @processed_elements;
@processed_elements = ();
$twig->purge;
}
有没有简单的xpath获取值的方法?
我知道有一种可能性是这样的:
my $Xtnsn_Txt1 = $twig->first_elt( sub { $_[0]->tag eq 'PlcAndNm' && $_[0]->text eq 'ext_1' })->next_sibling()->text();
但我更喜欢使用最简单的 XPath 语法,
在此先感谢您的帮助!
另一种方法可能是:
//Txt[preceding-sibling::PlcAndNm[.="ext_1"]]
您还可以稍微修改一下您的 XPath 表达式,看看它是否适用于 :
//Xtnsn[./PlcAndNm[contains(.,"ext_1")]]/Txt
编辑:这适用于原始的 XML::XPath 模块:
use XML::XPath;
use XML::XPath::Node::Element;
my $xp = XML::XPath->new(filename => 'pathtoyour.xml');
my $nodeset = $xp->find('//Xtnsn[PlcAndNm="ext_1"]/Txt');
foreach my $node ($nodeset->get_nodelist) {
print XML::XPath::Node::Element::string_value($node),"\n\n";
}
输出:1234 9876
你可以使用这个:
my $Xtnsn_Txt1 = $twig->findvalue('//Xtnsn/PlcAndNm[string()="ext_1"]/../Txt');
最近我开始使用 XML::Twig::XPath 但该模块似乎无法识别 xpath 语法。 在下面XML中,如果PlcAndNm节点的值为"ext_1"
,我想要"Txt"节点的值<?xml version="1.0" encoding="UTF-8"?>
<root>
<Document>
<RedOrdrV03>
<MsgId>
<Id>1</Id>
</MsgId>
<Xtnsn>
<PlcAndNm>ext_1</PlcAndNm>
<Txt>1234</Txt>
</Xtnsn>
<Xtnsn>
<PlcAndNm>ext_2</PlcAndNm>
<Txt>ABC</Txt>
</Xtnsn>
</RedOrdrV03>
</Document>
<Document>
<RedOrdrV03>
<MsgId>
<Id>2</Id>
</MsgId>
<Xtnsn>
<PlcAndNm>ext_1</PlcAndNm>
<Txt>9876</Txt>
</Xtnsn>
<Xtnsn>
<PlcAndNm>ext_2</PlcAndNm>
<Txt>DEF</Txt>
</Xtnsn>
</RedOrdrV03>
</Document>
</root>
我已经尝试过 whit 表达式 //Xtnsn[PlcAndNm="ext_1"]/Txt 但我收到了一个错误 这是代码:
use XML::Twig::XPath;
my $subelt_count = 1;
my @processed_elements;
my $xmlfile = 'c:/test_file.xml';
my $parser = XML::Twig->new(
twig_roots => { 'RedOrdrV03' => \&process_xml } ,
end_tag_handlers => { 'Document' },
);
$parser->parsefile($xmlfile);
sub process_xml {
my ( $twig, $elt ) = @_;
push( @processed_elements, $elt );
if ( @processed_elements >= $subelt_count ) {
my $MsgId = $twig->findvalue('RedOrdrV03/MsgId/Id');
my $Xtnsn_Txt1 = $twig->findvalue('//Xtnsn[PlcAndNm="ext_1"]/Txt');
print "MsgId: $MsgId - Xtnsn_Txt1: $Xtnsn_Txt1\n";
}
$_->delete for @processed_elements;
@processed_elements = ();
$twig->purge;
}
有没有简单的xpath获取值的方法? 我知道有一种可能性是这样的:
my $Xtnsn_Txt1 = $twig->first_elt( sub { $_[0]->tag eq 'PlcAndNm' && $_[0]->text eq 'ext_1' })->next_sibling()->text();
但我更喜欢使用最简单的 XPath 语法,
在此先感谢您的帮助!
另一种方法可能是:
//Txt[preceding-sibling::PlcAndNm[.="ext_1"]]
您还可以稍微修改一下您的 XPath 表达式,看看它是否适用于 :
//Xtnsn[./PlcAndNm[contains(.,"ext_1")]]/Txt
编辑:这适用于原始的 XML::XPath 模块:
use XML::XPath;
use XML::XPath::Node::Element;
my $xp = XML::XPath->new(filename => 'pathtoyour.xml');
my $nodeset = $xp->find('//Xtnsn[PlcAndNm="ext_1"]/Txt');
foreach my $node ($nodeset->get_nodelist) {
print XML::XPath::Node::Element::string_value($node),"\n\n";
}
输出:1234 9876
你可以使用这个:
my $Xtnsn_Txt1 = $twig->findvalue('//Xtnsn/PlcAndNm[string()="ext_1"]/../Txt');