プロが教えるわが家の防犯対策術!

Perlを用いて、XMLファイルの中のキーワードの個数を数えるプログラムを組もうと思っています。
次のようなXMLの中の<keyword>のタグに囲まれた文字列を数えるプログラムです。

<?xml version="1.0" encoding="UTF-8"?>
<grant_award_list>
<grant_award id="1001">
<title>タイトル1</title>
<keywords><keyword>A</keyword><keyword>B</keyword></keywords>
</grant_award>
<grant_award id="1002">
<title>タイトル2</title>
<keywords><keyword>B</keyword></keywords>
</grant_award>
</grant_award_list>

このようなときに、次のようにキーワードとその出現回数が記載されたXMLファイルにしたいと考えています。

<?xml version="1.0" encoding="UTF-8"?>
<keywords>
<keyword>A</keyword>
<count>1</count>
</keywords>
<keywords>
<keyword>B</keyword>
<count>2</count>
</keywords>

具体的なプログラムのコードを教えてください。よろしくお願いします。

A 回答 (3件)

表示がくずれるので、以下、スペース2文字を全角のスペースにして書いてあることに注意


use XML::TreePP;

my $file = shift || 'tmp.xml';
my $tpp = XML::TreePP->new( utf8_flag => 1 );
my $tree_in = $tpp->parsefile($file);

my %count_of = ();
for my $hash_ref ( @{ $tree_in->{grant_award_list}->{grant_award} } ) {
  my $keyword = $hash_ref->{keywords}->{keyword};
  if ( ref($keyword) eq 'ARRAY' ) {
    for my $item ( @{$keyword} ) {
      $count_of{$item}++;
    }
  }
  else {
    $count_of{$keyword}++;
  }
}

my $tree_out;
my $index = 0;
while ( my ( $keyword, $count ) = each %count_of ) {
  $tree_out->{keywords}->[$index]->{keyword} = $keyword;
  $tree_out->{keywords}->[$index]->{count}  = $count;
  $index++;
}
my $xml = $tpp->write($tree_out);
print $xml;

この回答への補足

早速のお返事ありがとうございます。

<keyword>ではさまれた要素に漢字やひらがなを含んでいるため、文字化けしてしまいました。

どのようにすれば解決できますでしょうか。
よろしくお願いいたします。

補足日時:2010/05/27 22:00
    • good
    • 0

use XML::TreePP;


use Encode;

my $file = shift || 'tmp.xml';
my $tpp = XML::TreePP->new( utf8_flag => 1 );
my $tree_in = $tpp->parsefile($file);

my %count_of = ();
for my $hash_ref ( @{ $tree_in->{grant_award_list}->{grant_award} } ) {
  my $keyword = $hash_ref->{keywords}->{keyword};
  if ( ref($keyword) eq 'ARRAY' ) {
    for my $item ( @{$keyword} ) {
      $count_of{$item}++;
    }
  }
  else {
    $count_of{$keyword}++;
  }
}

my $tree_out;
my $index = 0;
while ( my ( $keyword, $count ) = each %count_of ) {
  $tree_out->{keywords}->[$index]->{keyword} = $keyword;
  $tree_out->{keywords}->[$index]->{count}  = $count;
  $index++;
}

# encoding="UTF-8" なのでutf8で出力する。
my $xml = encode( "utf8", $tpp->write($tree_out) );
print $xml;

この回答への補足

ありがとうございます。

やはり文字化けしてしまいました。
モジュールが合わないということなのでしょうか。

補足日時:2010/05/27 23:40
    • good
    • 0

最後にutf8で出力しているところで文字化けしているんじゃないですか?


cp932、shiftjis、eucjpなど適切なエンコードを指定して下さい。

あまり関係ないけどちょっと書き直し(全角空白あり注意)
use XML::TreePP;
use Encode;

my $file = shift || 'tmp.xml';
my $tpp = XML::TreePP->new( utf8_flag => 1, force_array => ['keyword'] );
my $tree_in = $tpp->parsefile($file);

my %count_of = ();
for my $hash_ref ( @{ $tree_in->{grant_award_list}->{grant_award} } ) {
  my $keyword = $hash_ref->{keywords}->{keyword};
  for my $item ( @{$keyword} ) {
    $count_of{$item}++;
  }
}
my $tree_out = {};
$tree_out->{keywords}
  = [ map { { keyword => [$_], count => $count_of{$_} } } keys %count_of ];

my $xml = encode( "utf8", $tpp->write($tree_out) );
print $xml;

この回答への補足

何度もありがとうございます。

cp932、shiftjis、eucjpなど試してみましたが、どれも文字化けしてしまいました。
XMLファイルの保存形式や文字コードも確認しましたが、やはり無理でした。

補足日時:2010/05/31 01:12
    • good
    • 0
この回答へのお礼

コマンドプロンプトによる表示が原因でした。

頂いたプログラムによってXMLファイルを生成したら、正常に表示されていました。

本当にありがとうございました。

お礼日時:2010/05/31 21:30

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!