检查属性的特定值,并使用XML::LibXML在Perl中使用XPath提取sibblings值
如果检查属性的特定值,并使用XML::LibXML在Perl中使用XPath提取sibblings值,perl,xpath,libxml2,Perl,Xpath,Libxml2,如果solve是user,我需要name(行)的值 如果solve是imm并且name是ARCH,我需要value(6M)的值 我尝试了以下方法: use strict; use warnings; use XML::LibXML; my $parser = XML::LibXML->new(); my $doc = $parser->parse_file(...); my $j = 0; my @imm; $imm[$j++] = $_->data foreach
solve
是user
,我需要name
(行
)的值
如果solve
是imm
并且name是ARCH
,我需要value
(6M
)的值
我尝试了以下方法:
use strict;
use warnings;
use XML::LibXML;
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file(...);
my $j = 0;
my @imm;
$imm[$j++] = $_->data
foreach
$doc->findnodes(
"//meters/meter"
."/name[../value[\@solve/string() = 'immediate']]"
."/text()");
错误是
Possible unintended interpolation of @solve in string
Global symbol "@solve" requires explicit package name
示例XML:
<rules>
<meters>
<meter>
<name>LINES</spirit:name>
<display>LINES</display>
<description>Specifies the number of lines</description>
<value
solve="user"
id="LINES"
order="11"
format="long"
dataType="integer"
min="2"
max="34">34</value>
</meter>
<meter>
<name>ARCH</name>
<display>Define ARCH</display>
<description>Define ARCH</description>
<value
format="string"
solve="imm"
id="ARCH"
>6M</value>
</meter>
</meters>
</rules>
<rules>
<meters>
<meter>
<name>LINES</spirit:name>
<display>LINES</display>
<description>Specifies the number of lines</description>
<value
solve="user"
id="LINES"
order="11"
format="long"
dataType="integer"
min="2"
max="34">34</value>
</meter>
<meter>
<name>ARCH</name>
<display>Define ARCH</display>
<description>Define ARCH</description>
<value
format="string"
solve="imm"
id="ARCH"
>6M</value>
</meter>
</meters>
</rules>
线
线
指定行数
34
拱门
定义拱门
定义拱门
6米
线
线
指定行数
34
拱门
定义拱门
定义拱门
6米
一个快速而肮脏的黑客来解决您的问题-使用XML::Simple
:
use strict;
use warnings;
use XML::Simple ;
use Data::Dumper;
my $xml = XMLin(qq|
<xml>
<rules>
<meters>
<meter>
<name>LINES</name>
<display>LINES</display>
<description>Specifies the number of lines</description>
<value
solve="user"
id="LINES"
order="11"
format="long"
dataType="integer"
min="2"
max="34">34</value>
</meter>
<meter>
<name>ARCH</name>
<display>Define ARCH</display>
<description>Define ARCH</description>
<value
format="string"
solve="imm"
id="ARCH"
>6M</value>
</meter>
</meters>
</rules>
<rules>
<meters>
<meter>
<name>LINES</name>
<display>LINES</display>
<description>Specifies the number of lines</description>
<value
solve="user"
id="LINES"
order="11"
format="long"
dataType="integer"
min="2"
max="34">34</value>
</meter>
<meter>
<name>ARCH</name>
<display>Define ARCH</display>
<description>Define ARCH</description>
<value
format="string"
solve="imm"
id="ARCH"
>6M</value>
</meter>
</meters>
</rules>
</xml>|,
ForceArray => 1);
foreach my $rule( @{ $xml->{rules} } ){
foreach my $meter ( @{ $rule->{meters} } ){
foreach my $m ( @{ $meter->{meter} } ){
if ( $m->{value}->{LINES} and $m->{value}->{LINES}->{solve} eq 'user' ) {
print "user solver: ".$m->{name}->[0]."\n";
} elsif ( $m->{value}->{ARCH}->{solve} and $m->{name}->[0] and $m->{value}->{ARCH}->{solve} eq 'imm' and $m->{name}->[0] eq 'ARCH' ) {
print "imm solver: ".Dumper( $m->{value}->{ARCH}->{content})."\n";
} else {
print "no solver???".Dumper($m);
}
}
}
}
使用严格;
使用警告;
使用XML::Simple;
使用数据::转储程序;
我的$xml=XMLin(qq|
线
线
指定行数
34
拱门
定义拱门
定义拱门
6米
线
线
指定行数
34
拱门
定义拱门
定义拱门
6米
|,
ForceArray=>1);
foreach my$rule(@{$xml->{rules}){
foreach my$meter(@{$rule->{meters}){
每个我的$m(@{$meter->{meter}}{
if($m->{value}->{LINES}和$m->{value}->{LINES}->{solve}eq'user'){
打印“用户解算器:”..m->{name}->[0]。“\n”;
}elsif($m->{value}->{ARCH}->{solve}和$m->{name}->[0]和$m->{value}->{ARCH}->{solve}eq'imm'和$m->{name}->[0]eq'ARCH')){
打印“imm解算器:”.Dumper($m->{value}->{ARCH}->{content})。“\n”;
}否则{
打印“无解算器?”。转储程序(百万美元);
}
}
}
}
我希望你能以此为出发点
观察结果
- 鉴于
es只包含一条指令(如果foreach
),它们可以被重写为if
映射,尽管我不鼓励这样做
也可以使用if
和三元运算符
结果字符串重写打印
- 考虑到以上所有因素,整个XML处理过程可以在一行中重写,该行由3个
s和2个三元操作组成,我认为这几乎是不可读的map
- 这对我来说很有用:
#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;
my $parser = XML::LibXML->new();
my $doc = $parser->parse_file('XXX.xml');
my $j = 0;
my @imm;
$imm[$j++] = $_->data
for $doc->findnodes(
"//meters/meter"
."/name[../value[\@solve = 'imm']]"
."/text()");
print for @imm;
我对您的代码进行了以下更改:
/string()
部分。正如我得到的错误所表明的那样,函数的使用是无效的solve
的值是imm
,而不是immediate
'/name[../value[@solve = "immediate"]]'
避免使用反斜杠。如果solve=“user”我需要name的值(即行)。如果solve=“imm”,如果name是ARCH,我需要使用xml::lib-xml得到value的值(即6M),我用这种方式尝试了$parser=xml::LibXML->new();my$doc=$parser->parse_file();我的$j=0;我的@imm;$imm[$j++]=$\->data foreach($doc->findnodes(“//meters/meter/name[../value[\@solve/string()='immediate']]/text()”);错误可能是字符串全局符号“@solve”中的@solve的意外插入需要显式的包名我无法放置代码行行指定行数34 ARCH Define ARCH Define ARCH 6M”“修正了密码。现在将问题添加到节点中。我使用的是xml::libxml,所以请您使用xpath和xml::libxml编写。我对这些都不熟悉。为什么会出现错误?foreach$doc->findnodes(“//meters/meter”。“/name[../value[\@solve/string()='immediate']]”“/text()”;我得到这些错误XPath错误:未定义的名称空间前缀;错误:XmlXPathCompiledVal:计算失败。如果在@之前删除\,它将作为数组进行检测。。。有谁能解决这个问题吗?但我遇到了以下错误:XPath错误:未定义名称空间前缀错误:XmlXPathCompiledVal:计算失败;对于相同的代码;我使用了这个xpath;'//meters/meter/name[../value[@solve=“imm”]]/text()'您的XML包含名称空间声明(搜索
xmlns
)。有关如何处理名称空间的信息,请参见。