简单的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');
}
谁能看到我哪里出错了?
干杯
答案 0 :(得分: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>
答案 1 :(得分:1)
XML::LibXML
以下内容直接访问Text Node,以便简单轻松地更改随附的文字:
#!/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>
答案 2 :(得分:0)
my $value = $critics->findvalue('name'); #returns the correct name
$value->removeChildNodes();
$value->appendText('new_name');
$value
是一个简单的标量,用于保存找到的xml元素<name>…</name>
的文本。您不能在&#39;字符串上调用任何这些方法,可以吗?
答案 3 :(得分:-1)
试着让你进入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__
享受!