0

我有一个如下所示的 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>

我按类型对 XMLin 进行排序 - 所以 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";
        }

我正在尝试打印出类型,并且只有在我知道类型的情况下才有效。最终,我想输入书的类型和标题,但现在,如果我可以打印出类型,那就太好了。

4

2 回答 2

2

我将重复我在回答您之前的问题时所建议的内容:取消引用 XML::Simple 哈希

不要使用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
于 2014-07-25T22:56:02.657 回答
1

键“book”的结构是一个哈希引用,但是您将它视为一个数组引用 ( @{$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} );
}
于 2014-07-25T22:46:36.687 回答