PerlXML::LibXML替换文本



简单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 detailsn" 
    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');

}

有人看到我哪里出错了吗?

干杯

使用XML::LibXML的解决方案

以下内容直接访问文本节点,以简单轻松地更改所附文本:

#!/usr/bin/perl
use strict;
use warnings;
use XML::LibXML;
my $doc = XML::LibXML->load_xml( IO => *DATA );
for my $text ( $doc->findnodes('//reviewer/name/text()') ) {
    $text->setData('new_name');
}
print $doc->toString;
__DATA__
<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>

使用XML::Twig的解决方案

取每个评审员的名字,并将其颠倒过来:

use strict;
use warnings;
use XML::Twig;
my $t= XML::Twig->new( 
    twig_handlers => {
        q{//reviewer/name} => sub { $_->set_text(scalar reverse $_->text()) },
    },
    pretty_print => 'indented',
);
$t->parse( do { local $/; <DATA> } );
$t->print;
__DATA__
<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>

输出:

<book_reviewers>
  <results>
    <reviewer>
      <name>ennA</name>
      <profession>Catfish wrangler</profession>
    </reviewer>
    <reviewer>
      <name>boB</name>
      <profession>Beer taster</profession>
    </reviewer>
    <reviewer>
      <name>eilrahC</name>
      <profession>Gardener</profession>
    </reviewer>
  </results>
</book_reviewers>

问题是这个调用

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 reviewersn";
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>
my $value = $critics->findvalue('name');    #returns the correct name
$value->removeChildNodes();
$value->appendText('new_name');

$value是一个简单的标量,它保存找到的xml元素<name>…</name>的文本。你不能在"字符串"上调用这些方法中的任何一个,是吗?

试图让你进入TIMTOWTDI,这里是另一个代码更紧凑的例子:

您可以直接找到所有<name>…</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__

享受吧!

相关内容

  • 没有找到相关文章

最新更新