0

如果solveuser,我需要name( LINES) 的值。

如果solveisimm和 name is 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>
4

2 回答 2

1

一个快速而肮脏的黑客来解决您的问题 - 使用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);
      }
    }    
  }
}

我希望你可以以此为起点。

观察

  • 鉴于foreaches 仅包含一条指令(the if),它们可以重写为maps,尽管我不鼓励这样做
  • if也可以使用和ternary operator结果print字符串重写
  • 考虑到以上所有因素,整个 XML 处理可以重写为由 3 个map和 2 个三元操作组成的一行 - 我认为它几乎不可读
于 2012-11-06T07:06:13.160 回答
1

这对我有用:

#!/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;

我对您的代码进行了以下更改:

  1. /string()从 XPath 表达式中删除了该部分。正如我得到的错误所示,这是对函数的无效使用。
  2. 的值solveimm您的样本数据中,而不是immediate.

顺便说一句,将 XPath 表达式的中间更改为

'/name[../value[@solve = "immediate"]]'

避免使用反斜杠。

于 2012-11-06T08:34:17.220 回答