Perl XML::LibXML替换值

Perl XML::LibXML替换值,perl,Perl,我有下面的xml文件,在这里我想写一个perl脚本,这样我可以grep第一本书的名字,然后是作者的名字,如果两者都匹配,将字段“value”从false改为true。例如,如果书名为abc,作者名为john,请将值从false更改为true use warnings; use strict; use XML::LibXML; my $parser = XML::LibXML->new(); my $xmldoc = $parser->parse_file('b.xml'); for

我有下面的xml文件,在这里我想写一个perl脚本,这样我可以grep第一本书的名字,然后是作者的名字,如果两者都匹配,将字段“value”从false改为true。例如,如果书名为abc,作者名为john,请将值从false更改为true

use warnings;
use strict;
use XML::LibXML;
my $parser = XML::LibXML->new();
my $xmldoc = $parser->parse_file('b.xml');
for my $book ($xmldoc->findnodes('/library/book')) {
    my $name = $book->findvalue('/@name');
    if($name eq "abc")
    {
        print "yes" ;
    }
}


我是perl新手,有人能帮我吗?我已经写了一些代码,以达到第一点,检查作者姓名,但这本身是不起作用的

for my $default_author_node ($xmldoc->findnodes(
   '/library/book[@name="abc"]/author[@name="john"]/default'
)) {
   $default_author_node->setAttribute('value', 'true');
}
但您可能希望名称是可变的

解决方案1:动态构建上述XPath

sub text_to_xpath {
   my ($s) = @_;
   return qq{"$s"} if $s !~ tr/"//;
   return qq{'$s'} if $s !~ tr/'//;
   $s = s/"/", '"', "/g;
   return qq{concat("$s")};
}

my $target_book_xp   = text_to_xpath($target_book);
my $target_author_xp = text_to_xpath($target_author);

for my $default_author_node ($xmldoc->findnodes(
   "/library/book[\@name=$target_book_xp]/author[\@name=$target_author_xp]/default"
)) {
   $default_author_node->setAttribute('value', 'true');
}
解决方案2:自己做检查

这就是您尝试的,但是XPath
/@name
会在文档的根(
/
)获取名为
name
)的子属性(
@
),但其中唯一的节点是根元素(
)。就像在目录路径中一样,如果要相对于上下文进行搜索,请不要使用前导的
/

for my $book_node ($xmldoc->findnodes('/library/book')) {
   my $name = $book_node->getAttribute('name');
   next if !defined($name) || $name ne $target_book;

   for my $author_node ($book_node->findnodes('author')) {
      my $name = $book_node->getAttribute('name');
      next if !defined($name) || $name ne $target_author;

      for my $default_author_node ($author_node->findnodes('default')) {
         $default_author_node->setAttribute('value', 'true');
      }
   }
}

感谢您对解决方案2的帮助,它成功了。我还有一个问题,我想更改同一xml文件中的内容。有办法吗?现在我正在使用print$xmldoc->toString;以及将输出重定向到另一个xml文件。但我不喜欢这样做。没有什么能阻止你保存到同一个文件。还有一个名为
toFile
的方法,它将为您节省一些工作
for my $book_node ($xmldoc->findnodes('/library/book')) {
   my $name = $book_node->getAttribute('name');
   next if !defined($name) || $name ne $target_book;

   for my $author_node ($book_node->findnodes('author')) {
      my $name = $book_node->getAttribute('name');
      next if !defined($name) || $name ne $target_author;

      for my $default_author_node ($author_node->findnodes('default')) {
         $default_author_node->setAttribute('value', 'true');
      }
   }
}