XML :: LibXML替换值

时间:2015-02-13 16:45:49

标签: perl

我有下面的xml文件,在这里我想编写一个perl脚本,这样我就可以在第一本书名称和作者名称上进行grep,如果两者匹配,则更改字段" value"从虚假到真实。例如,如果书名是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" ;
    }

}

<library>
  <book name="abc" id="3">
    <key name="history">
      <default label="base" value="1"/>
    </key>
    <author name="john">
      <default label="base" value="false"/>
    </author>
  </book>
  <book name="xyz" id="4">
    <key name="science">
      <default label="base" value="1"/>
    </key>
    <author name="nik">
      <default label="base" value="false"/>
    </author>
  </book>

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

1 个答案:

答案 0 :(得分:2)

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的子属性(/),但是只有节点有根元素(library)。就像在目录路径中一样,如果要相对于上下文进行搜索,请不要使用前导/

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');
      }
   }
}