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 に答える