0

の場合、 ( )の値が必要solveです。usernameLINES

solveimmで name がの場合、 ( )ARCHの値が必要ですvalue6M

私は次のように試しました:

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

これは私のために働く:

#!/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. の値はsolveサンプルimmデータにあり、 ではありませんimmediate

ところで、XPath式の真ん中を

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

バックスラッシュの必要性を回避します。

于 2012-11-06T08:34:17.220 に答える
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 には命令が 1 つしか含まれていないため (the ) if、それらを に書き換えることができますがmaps、私はそれをお勧めしません。
  • と結果の文字列を使用して書き換えるifこともできますternary operatorprint
  • 上記のすべてを考慮すると、XML 処理全体を 3 つmapの s と 2 つの 3 項 ops からなる 1 行で書き直すことができます。ほとんど判読できないと思います。
于 2012-11-06T07:06:13.160 に答える