人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

Perlを用いて下のようなxml形式のデータから情報を得たいと考えています。

--------------------------
<name id="1">
<keywords>
<keyword>a</keyword>
<keyword>b</keyword>
</keywords>
</name>
<name id="2">
<keywords>
<keyword>c</keyword>
</keywords>
</name>
<name id="3">
<keywords>
<keyword>d</keyword>
</keywords>
</name>



------------------------------
このようなxmlがあったとき、name id 1と2と3を選んだら、
以下のようにキーワードの組み合わせを習得し、
テキストに書き込むプログラムを教えてください。
お願いします。

a-b
a-c
a-d
b-c
b-d
c-d

●質問者: riyoooh
●カテゴリ:コンピュータ ウェブ制作
✍キーワード:name Perl XML キーワード テキスト
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● GreenStar
●40ポイント ベストアンサー

XML::Simpleを使った! コメントを全て外せばデバッグモード!!

#use Data::Dumper;
use XML::Simple;
@selectID = ('1', '2');
$readXML = XML::Simple -> new -> XMLin('a.xml', ContentKey => '-keywords', forcearray => 'keyword');
#warn Dumper($readXML);

@data = ();
foreach $id (@selectID) {
 foreach $values ($$readXML{'name'}{$id}{'keyword'}) {
 push(@data, @$values);
 }
}
#warn Dumper(@data);

$count = $#data;
open(OUT, ">a.txt");
for($i = 0; $i <= $count; $i++){
 for($k = $i + 1; $k <= $count; $k++){
 print OUT @data[$i] . '-' . @data[$k] . "\n";
 }
}
close(OUT);
<?xml version='1.0'?>
<root>
 <name id="1">
 <keywords>
 <keyword>a</keyword>
 <keyword>b</keyword>
 </keywords>
 </name>
 <name id="2">
 <keywords>
 <keyword>c</keyword>
 </keywords>
 </name>
 <name id="3">
 <keywords>
 <keyword>d</keyword>
 </keywords>
 </name>
</root>
◎質問者からの返答

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

本当に助かりました。参考にさせていただきます。

ところが少し内容がことなるxmlに適用したところ、次のようなエラーが出てしまいました。

No such pseudo-hash field "40037221" at xml01.pl line9.

ことなるxmlというのは

<name id="1"> の部分が、

<researcher id="40037221" permalink="http://・・・">

のようになっています。

そこでいただいたプログラムの3行目のselectIDを40037221のようにし、

9行目のnameの部分をresearcherとしたところ上記のエラーが発生してしまいました。

このエラーの解決方法を教えていただけないでしょうか。


2 ● TREEG
●20ポイント

誰も答えないので一応書いてみました。

ロジック間違ってたらすみません。

もっと良いやり方が絶対にありそうです。

use strict;

$| = 1;

#指定の番号を入れる

my @number = (1,2,3);


my @xml = <DATA>;

my @array; my $flag;

for my $number (@number){

for (@xml) {

if(m/<name id="${number}">/ || $flag){

if( my ($al) = ($_ =~ m!<keyword>(.*?)<\/keyword>!sig) ){

push(@array , $al );

}

$flag = 1;

}

if(m/<\/name>/){

$flag = 0;

}

}

}

for(;;){

for (@array) {

my $al1 = shift @array;

for my $al2 (@array){

open(F,">>text.txt");

print F "${al1}-${al2}\n";

print "${al1}-${al2}\n";

close(F);

}

}

unless(@array){last;};

}

__DATA__

<name id="1">

<keywords>

<keyword>a</keyword>

<keyword>b</keyword>

</keywords>

</name>

<name id="2">

<keywords>

<keyword>c</keyword>

</keywords>

</name>

<name id="3">

<keywords>

<keyword>d</keyword>

</keywords>

</name>

◎質問者からの返答

お返事おそくなりました。

早速試したところうまく動きました。

ありがとうございます。


3 ● GreenStar
●20ポイント

XMLファイルの構造が変わったのでプログラムを作り直しました! XMLに対して汎用的な対処法があれば私も知りたいです!!

#use Data::Dumper;
use XML::Simple;
@selectID = ('40037221', '40037222');
$readXML = XML::Simple -> new -> XMLin('a.xml', forcearray => 'keyword');
#warn Dumper($readXML);

@data = ();
foreach $id (@selectID) {
 $ref = $$readXML{'researcher'}{$id}{'keywords'}[0];
 foreach $values (@$ref{'keyword'}) {
 push(@data, @$values);
 }
}
#warn Dumper(@data);

$count = $#data;
open(OUT, ">a.txt");
for($i = 0; $i <= $count; $i++){
 for($k = $i + 1; $k <= $count; $k++){
 print OUT @data[$i] . '-' . @data[$k] . "\n";
 }
}
close(OUT);
<?xml version='1.0'?>
<root>
 <researcher id="40037221" permalink="http://example.jp/40037221">
 <keywords>
 <keyword>a</keyword>
 <keyword>b</keyword>
 </keywords>
 </researcher>
 <researcher id="40037222" permalink="http://example.jp/40037222">
 <keywords>
 <keyword>c</keyword>
 </keywords>
 </researcher>
 <researcher id="40037223" permalink="http://example.jp/40037223">
 <keywords>
 <keyword>d</keyword>
 </keywords>
 </researcher>
</root>
◎質問者からの返答

ありがとうございます。

xmlの形式が変わるごとに書き換えるのはめんどうですね。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ