打印出按属性排序的XML :: SImple哈希

时间:2014-07-25 22:09:44

标签: xml perl xml-simple

我有一个如下所示的XML文件:

<booklist>
   <book type="technical">
      <author>Book 1 author 1</author>
      <author>Book 1 author 2</author>
      <title>Book 1 title</title>
      <isbn>Book1ISBN</isbn>
   </book>
   <book type="fiction">
      <author>Book 2 author 1</author>
      <author>Book 2 author 2</author>
      <title>Book 2 title</title>
      <isbn>Book2ISBN</isbn>
   </book>
   <book type="technical">
      <author>Book 3 author 1</author>
      <author>Book 3 author 2</author>
      <author>Book 3 author 3</author>
      <title>Book 3 title</title>
      <isbn>Book3ISBN</isbn>
   </book>
</booklist>

我按类型对XML进行排序 - 所以XML :: Simple。 我认为这是一个很好的方法。 按类型整理每本书。

/tmp/walt $ cat bookparse_by_attrib.pl_dump
#!/usr/bin/perl
use strict ;
use warnings ;
use XML::Simple ;
use Data::Dumper ;
my $book = ();

my $booklist = XMLin('book.xml_with_attrib', KeyAttr => {book => 'type'});
#print Dumper($booklist);
print $booklist->{book}->{technical}->{title}  . "\n";


/tmp/walt $ ./bookparse_by_attrib.pl_dump
$VAR1 = {
          'book' => {
                    'technical' => {
                                   'author' => [
                                               'Book 3 author 1',
                                               'Book 3 author 2',
                                               'Book 3 author 3'
                                             ],
                                   'title' => 'Book 3 title',
                                   'isbn' => 'Book3ISBN'
                                 },
                    'fiction' => {
                                 'author' => [
                                             'Book 2 author 1',
                                             'Book 2 author 2'
                                           ],
                                 'title' => 'Book 2 title',
                                 'isbn' => 'Book2ISBN'
                               }
                  }
        };

这将打印出来:

print $booklist->{book}->{technical}->{title}  . "\n";
/tmp/walt $ ./bookparse_by_attrib.pl_dump
Book 3 title

所以当我知道类型名称时它会起作用 但是这会引发错误:

print $booklist->{book}->{type}->{title}  . "\n";
Use of uninitialized value in concatenation (.) or string at ./bookparse_by_attrib.pl_dump line 11.

这不会引发错误 - 但它不会打印出任何内容。

#!/usr/bin/perl
use strict ;
use warnings ;
use XML::Simple ;
use Data::Dumper ;
my $book = ();
my $booklist = ();

foreach my $book (@{$booklist->{book}}) {
        print $book->{title} . "\n";
        }

我正在尝试打印出类型,只有在我知道类型的情况下才能解决。 最后,我想输入书的类型和标题,但是现在,如果我可以打印出类型,那么tath会很棒。

2 个答案:

答案 0 :(得分:2)

我将在my answer中重复我之前提出的问题:dereferencing a XML::Simple hash

请勿使用XML::Simple。它是一个过时的模块,只会在您尝试破解它以提供所需格式时导致持续出现问题。

相反,使用XML::LibXML直接提取您想要的信息:

use strict;
use warnings;

use List::MoreUtils qw(uniq);
use XML::LibXML;

my $xml = XML::LibXML->load_xml(IO => \*DATA);

my @types = sort +uniq map {$_->textContent()} $xml->findnodes('//book/@type');

for my $type (@types) {
    print "Type = $type\n";

    for my $book ($xml->findnodes("//book[\@type='$type']")) {
        print "  Title = " . $book->findvalue('title') . "\n";
    }
}

__DATA__
<booklist>
   <book type="technical">
      <author>Book 1 author 1</author>
      <title>Book 1 title</title>
      <isbn>Book1ISBN</isbn>
   </book>
   <book type="fiction">
      <author>Book 2 author 1</author>
      <author>Book 2 author 2</author>
      <title>Book 2 title</title>
      <isbn>Book2ISBN</isbn>
   </book>
   <book type="technical">
      <author>Book 3 author 1</author>
      <author>Book 3 author 2</author>
      <author>Book 3 author 3</author>
      <title>Book 3 title</title>
      <isbn>Book3ISBN</isbn>
   </book>
</booklist>

输出:

Type = fiction
  Title = Book 2 title
Type = technical
  Title = Book 1 title
  Title = Book 3 title

答案 1 :(得分:1)

键的结构&#34;书&#34;是一个哈希引用,但是您将其视为数组引用(@{$booklist->{book}})。

这种数据结构化方式与您遇到的一般性问题在于它是100%的哈希值。一旦你有两本相同类型的书,你只会得到每种类型的最后一本书。

#!/usr/bin/perl
use warnings;
use strict;

my $booklist = {
    'book' => {
        'technical' => {
            'author' => [
                'Book 3 author 1',
                'Book 3 author 2',
                'Book 3 author 3'
            ],
            'title' => 'Book 3 title',
            'isbn' => 'Book3ISBN'
        },
        'fiction' => {
            'author' => [
                'Book 2 author 1',
                'Book 2 author 2'
            ],
            'title' => 'Book 2 title',
            'isbn' => 'Book2ISBN'
        }
    }
};

for my $book_type ( keys %{ $booklist->{book} } ) {
    printf( "Title: %s\n", $booklist->{book}->{$book_type}->{title} );
}