0

単純な xml ファイルcr.xml

<book_reviewers>
    <results>
        <reviewer>
            <name>Anne</name>
            <profession>Catfish wrangler</profession>
        </reviewer>
        <reviewer>
            <name>Bob</name>
            <profession>Beer taster</profession>
        </reviewer>
        <reviewer>
            <name>Charlie</name>
            <profession>Gardener</profession>
        </reviewer>
    </results>
</book_reviewers>

各レビュアーをループして名前を新しい名前に置き換えたい

私はこれらの両方の方法を使用しようとはしていませんが、これらの両方が機能するはずの形式で他の投稿を行っていますが、エラーが発生し続けます:

Can't locate object method "setData"

Can't locate object method "removeChildNodes

Can't locate object method "appendText"

#!/usr/bin/perl -w

use strict;
use XML::LibXML;

my $critics_file = "cr.xml";
my $parser = new XML::LibXML;   


print "Couldn't retrieve review details\n" 
    unless my $book_reviews  = $parser->parse_file($reviews_file);


foreach my $critics ($critic_details->findnodes('/book_reviewers/results/reviewer')) {

    my $value = $critics->findvalue('name');    #returns the correct name
    $value->removeChildNodes();
    $value->appendText('new_name');

     ##ONLY EITHER THE ABOVE METHOD OR THE ONE BELOW - NOT BOTH

    my $node  = $critics->findnodes('.//name.text()');#returns the correct name
    $node->setData('new_name');


}

誰が私が間違っているのかを見ることができますか?

乾杯

4

4 に答える 4

2

問題は、この呼び出し

my $value = $critics->findvalue('name')

要素の文字列コンテンツを返し、nameそれをオブジェクトとして処理しようとしていXML::LibXML::Elementます。

メソッド呼び出しを次のように変更するだけです

my ($value) = $critics->findnodes('name')

そして、すべてがうまくいくはずです。

これがあなたのプログラムの作業バージョンです。

#!/usr/bin/perl

use strict;
use warnings;

use XML::LibXML;

my $reviews_file = 'cr.xml';
my $parser = XML::LibXML->new;

my $doc = $parser->parse_file($reviews_file) or die "Couldn't parse book reviewers\n";

for my $reviewer ($doc->findnodes('/book_reviewers/results/reviewer')) {
  my ($name) = $reviewer->findnodes('name');
  $name->removeChildNodes;
  $name->appendText('new_name');  
}

print $doc->toString;

出力

<?xml version="1.0"?>
<book_reviewers>
    <results>
        <reviewer>
            <name>new_name</name>
            <profession>Catfish wrangler</profession>
        </reviewer>
        <reviewer>
            <name>new_name</name>
            <profession>Beer taster</profession>
        </reviewer>
        <reviewer>
            <name>new_name</name>
            <profession>Gardener</profession>
        </reviewer>
    </results>
</book_reviewers>
于 2014-05-19T09:14:46.370 に答える
0
my $value = $critics->findvalue('name');    #returns the correct name
$value->removeChildNodes();
$value->appendText('new_name');

$value見つかった xml-element のテキストを保持する単純なスカラーです<name>…&lt;/name>。「文字列」でこれらのメソッドを呼び出すことはできませんね。

于 2014-05-19T09:10:23.373 に答える
-2

あなたを TIMTOWTDI に引き込もうとして、よりコンパクトなコードを使用した別の例を次に示します。

すべての要素を直接見つけることができ<name>…&lt;/name>、「デフォルト」変数を使用して、それらをすぐに繰り返すことができます$_

use strict;
use warnings;

use utf8;

use XML::LibXML;

my $filename = "cr.xml";

my $parser = XML::LibXML->new();
my $critic_details = $parser->parse_file("$filename") or die;

my $new_name = "new_name";

# find ALL the <book_reviewers><results><reviewers><name> nodes
foreach ($critic_details
  ->findnodes("book_reviewers/results/reviewer/name")
) {
  $_->removeChildNodes();
  $_->appendText($new_name);
}

use XML::LibXML::PrettyPrint;
my $pretty = XML::LibXML::PrettyPrint->new(
  indent_string =>' ' x4,
  element       => {
    compact       => [qw| name profession |],
    }
  );
$pretty->pretty_print($critic_details);

print $critic_details->toString;

__END__

楽しい!

于 2014-05-19T09:31:54.023 に答える