個人事業主の方必見!確定申告のお悩み解決

PerlでXMLで必要なデータだけ抽出しようと考えています。
下のサンプルXMLを次のテキストに変換したいのですが
具体的な記述方法が知りたく質問しました。

さくら
 子供1
 子供2
きく
 子供3

正規表現でなくXMLパーサ?というもので解決したいです。「宿題ではありません、あしからず(^^;」


<?xml version="1.0">
<E1>
<E2>
<list>example1></list>
<list>example2></list>
...
</E2>
<E3>
<class name="さくら">
<heya>
<hito>
<seimei>子供1</seimei>
</hito>
<hito>
<seimei>子供2</seimei>
</hito>
</heya>
</class>

<class name="きく">
<heya>
<hito>
<seimei>子供3</seimei>
</hito>
</heya>
</class>

</E3>
</E2>
</E1>

このQ&Aに関連する最新のQ&A

A 回答 (2件)

XML::Simple モジュールを使った方法。


<?xml version="1.0">
は、
<?xml version="1.0" ?>
で文字コードは UTF-8
example1>
は、
example1
----------------------------------------------------------------
use encoding 'UTF-8', STDOUT => "shiftjis";
use XML::Simple;

my $xml;
{
local $/ = undef;
open(FILE, "<:encoding(UTF-8)", "data.xml");
$xml=<FILE>;
close(FILE);
}
my $tree = XMLin($xml, ForceArray => 1);

while(my ($name, $class) = each(%{$tree->{E3}[0]->{class}})) {
print $name . "\n";
for my $hito (@{$class->{heya}[0]->{hito}}){
print " ".$hito->{seimei}[0] ."\n";
}
}
    • good
    • 0

そのものずばり、"XML::Parser"というモジュールがあります。


以下のURLに基本的な使い方が載っていますので、参考にされてはいかがでしょうか。

参考URL:http://lightly.plala.jp/memo/xml.html
    • good
    • 1

このQ&Aに関連する人気のQ&A

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

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q数値かどうかの判定方法

$aに代入されているものが数値かどうかを判定するにはどのようにしたらよいのでしょうか?

Aベストアンサー

$a =~ /^[0-9]*$/
上記の場合、*は「直前のパターンの0回以上の繰り返し」の意味なので、0から9がなくても、つまり$aが空でもマッチしてしまいます。
なので、
$a =~ /^[0-9]+$/
としましょう。
(+は「直前のパターンの1回以上の繰り返し」)
また、0-9は\dで表すこともできるので
$a =~ /^\d+$/
と書くこともできます。

QPerlによるXMLからCSVへの変換について

Perl初心者です。

下記のようなXMLファイル(test.xml)を、CSVに変換したいと考えています。
<MODESMESSAGE>
<DATETIME>20121129045500</DATETIME>
<MODES>8515C4</MODES>
<CALLSIGN>JAL1406</CALLSIGN>
<ALTITUDE>03075</ALTITUDE>
<GROUNDSPEED>177</GROUNDSPEED>
<TRACK>330</TRACK>
<VRATE>-832</VRATE>
<AIRSPEED>000</AIRSPEED>
<LATITUDE>35.4003</LATITUDE>
<LONGITUDE>139.8822</LONGITUDE>
<SQUAWK>3341</SQUAWK>
</MODESMESSAGE>
<MODESMESSAGE>
<DATETIME>20121129045500</DATETIME>
<MODES>86CF11</MODES>
<ALTITUDE>20100</ALTITUDE>
<VRATE>0</VRATE>
<AIRSPEED>000</AIRSPEED>
<LATITUDE>0</LATITUDE>
<LONGITUDE>0</LONGITUDE>
</MODESMESSAGE>

データによって、要素が欠けている場合もありますが、最大で11個の要素が並んでいます。

これをCSVに変換するため、書籍を参考にしながら以下のスクリプトxml2csv.plを作りました。
使用している環境はLinuxです。

use encoding "utf8", STDOUT=>"Shift_JIS";
use XML::Parser;

$parser = new XML::Parser( Handlers =>
{Start=>\&element_start,
Char => \&cdata,
End => \&element_end});

$element_name = '';
%records = {};

eval ( "\$parser->parsefile( \@ARGV[0] );");

if ($@) {
chomp($@);
$@ =~ s/^\n//;
$@ =~ s/ at (?:[A-Z]:)?\/.*//;
print @ARGV[0] . " :Error $@ \n";
}

sub element_start {
my ($expat, $name, %attributes) = @_;
$element_name = $name;
$records = {} if ( $name eq 'MODESMESSAGE' );
}

sub element_end {
my ($expat, $name) = @_;
if ( $name eq 'MODESMESSAGE' ) {
print $records{'DATETIME'} . "," . $records{'MODES'} . "," . $records{'CALLSIGN'} . "," . $records{'ALTITUDE'} . "," . $records{'GROUNDSPEED'} . "," . $records{'TRACK'} . "," . $records{'VRATE'} . "," . $records{'AIRSPEED'} . "," . $records{'LATITUDE'} . "," . $records{'LONGITUDE'} . "," . $records{'SQUAWK'} . "\n";
}
$element_name = '';
}

sub cdata {
my ($expat, $context) = @_;
$records{$element_name} = $context if ($element_name);
}

実行すると、
> perl xml2csv.pl test.xml
20121129045500,8515C4,JAL1406,03075,177,330,-832,000,35.4003,139.8822,3341
test.xml :Error junk after document element at line 14, column 0, byte 345
>
上記の通り1つ目のデータについてはCSVに変換できているようなのですが、2つ目以降が変換されずエラーとなってしまいます。

お気づきの点がありましたら教えていただけないでしょうか。
よろしくお願いします。

Perl初心者です。

下記のようなXMLファイル(test.xml)を、CSVに変換したいと考えています。
<MODESMESSAGE>
<DATETIME>20121129045500</DATETIME>
<MODES>8515C4</MODES>
<CALLSIGN>JAL1406</CALLSIGN>
<ALTITUDE>03075</ALTITUDE>
<GROUNDSPEED>177</GROUNDSPEED>
<TRACK>330</TRACK>
<VRATE>-832</VRATE>
<AIRSPEED>000</AIRSPEED>
<LATITUDE>35.4003</LATITUDE>
<LONGITUDE>139.8822</LONGITUDE>
<SQUAWK>3341</SQUAWK>
</MODESMESSAGE>
<MODESMESSAGE>
<DATETIME>20121129045500</DA...続きを読む

Aベストアンサー

test.xml の中身を

<XMLDOC>
<MODESMESSAGE>
...
<MODESMESSAGE>
<MODESMESSAGE>
...
<MODESMESSAGE>
...
</XMLDOC>

のようにタグで挟めば、よいと思う。 <XMLDOC> は単なる例で別に何でもよい。

よく知らないんだけど、挟まないとひとつの XML 文書にならないのじゃないかな ???

QXML::Simpleの使い方について

下記のような、プログラムを書いたのですが、上のタイトルはとれるのですが、連続して出てくるentryがどうしても取得できません。
何かご助言頂ければありがたいです。

my $url = "http://blog.livedoor.jp/takapon_ceo/atom.xml";

my $xml = get($url);
my $tree = XMLin($xml);

my $title = $tree->{title};
print "$title";

for (my $i = 0; $i <= 5; $i++) {
$id[$i] = $tree->{'entry'}->[$i]->{'id'};
print "$id[$i]";
}

よろしくお願いします。

Aベストアンサー

use Data::Dumper; をして Dumper($tree->{entry}) を表示すれば分かりますが、その実体は配列ではなくハッシュです。
このハッシュのキーは各エントリの id で、id は投稿順に文字列昇順となっていますから、キーをソートして値を取り出せばOKです。

# IDリストの取り出し(新着順にしたいので降順にソート)
my @entries_id = sort {$b cmp $a} keys %{$tree->{entry}};

foreach my $id (@entries_id) {
  print "$id\n";

  # 各要素へのアクセス
  my $entry = $tree->{entry}->{$id};
  print "$entry->{title}\n";
  print "$entry->{summary}->{content}\n";
}

# この結果は $tree = XMLin($xml) とした場合のものです。
# インデントに全角空白を使っているので、コピーする場合はタブなどに置換して下さい。

use Data::Dumper; をして Dumper($tree->{entry}) を表示すれば分かりますが、その実体は配列ではなくハッシュです。
このハッシュのキーは各エントリの id で、id は投稿順に文字列昇順となっていますから、キーをソートして値を取り出せばOKです。

# IDリストの取り出し(新着順にしたいので降順にソート)
my @entries_id = sort {$b cmp $a} keys %{$tree->{entry}};

foreach my $id (@entries_id) {
  print "$id\n";

  # 各要素へのアクセス
  my $entry = $tree->{entry}->{$id};
 ...続きを読む

Q参照配列の要素数の求め方は?

リファレンス配列の要素数は、$#では求められないのでしょうか?

-------------------------------------
foreach $i(0 .. 3){
$hash->[$i] = $i * 100;
}
print "\%hashの要素数->$#hash\n";

$ref = \%hash;
print "\%{$ref}の要素数->$#{$ref}\n";
-------------------------------------

Aベストアンサー

んーと
配列のリファレンスをつかった例でしたら...


foreach $i(0 .. 3){
$hash[$i]->{'v'} = $i * 100;
}

# 配列@hashへのリファレンス
$ref = \@hash;

# デリファレンス
@copy = @{$ref};

print "\$refの要素数->$#$ref\n";
print "\@copyの要素数->$#copy\n";


あと配列 @hash と連想配列 %hashは内容は別物ですので
期待した動きにならないのだと思います...

Q$1 と =~ の意味を教えて下さい

perlで書かれたとある掲示板に機能追加すべくソースをいじってます。
意味のわからないコードがあるので、教えて下さい。

$skin =~ s/(name="s_word")/$1 value="$in{s_word}"

とか、

$hogehoge = $1;

のような感じで出てくる、$1ってどういう変数なのでしょうか?
どういったときに用いられるのでしょう?

また、=~ というのは、どういう意味なのでしょうか?

どなたか、ご教授下さいませ。
よろしくお願い致します。

Aベストアンサー

> $hogehoge = $1; の場合の、$1は違う意味合いになるのでしょうか?

この $1 も同じものです。
よく似たものに \1 という後方参照用の特殊変数があります。働きは $1 と全く同じです。
たとえば、HTMLから「前後を対のタグで挟まれた部分」を探すとき、
<.+?>.*?</.+?>
と書いてしまうと、「<LI>ABC</UL>」なんていうのまでマッチしてしまいますよね。
そうではなく、「ULで始まったらULで閉じている部分」をマッチさせたいときは、
<(.+?)>.*?</\1>
と書きます。そうすると「<UL><LI>ABC</UL>」というように、正しい対になっている部分にのみマッチします。
最初の括弧の部分で見つけたものが、\1 に格納されているからです。
ところが、\1 や \2 は、その寿命(値保持)はパターンの中だけです。たとえば、見つけた後にその見つけたタグは何だったのか?処理の中で使いたいときがあり、そんなとき使えるのが $1 や $2 です。こちらは \1 や \2 と働きは同じで、その寿命が長いものです。具体的には、ブロック{}の中、または次に他の値が入れられるまで値を保持しています。

if (/<(.+?)>(.*?)</$1>/) {
print "$1 タグで挟まれた部分は「$2」です。"
}

ちなみに、後方参照用の特殊変数には、
$+
$&
$`
$'
などもあります。

> $hogehoge = $1; の場合の、$1は違う意味合いになるのでしょうか?

この $1 も同じものです。
よく似たものに \1 という後方参照用の特殊変数があります。働きは $1 と全く同じです。
たとえば、HTMLから「前後を対のタグで挟まれた部分」を探すとき、
<.+?>.*?</.+?>
と書いてしまうと、「<LI>ABC</UL>」なんていうのまでマッチしてしまいますよね。
そうではなく、「ULで始まったらULで閉じている部分」をマッチさせたいときは、
<(.+?)>.*?</\1>
と書きます。そうすると「<UL><LI>ABC</UL>」とい...続きを読む

QLInuxとWindowsでのPerlの動作の違い

LinuxでCGI(Perl)プログラムを作っています。

いつも動きの確認は自分のPC(Linux)と友人のPC(LInux)で行なっていました。

そして、昨夜別の友人のPC(Windows XP)を使う機会があってついでにそのPC上でプログラムを動かしてみたら一部が正確に動作してくれませんでした。でも、その後自分のPCで実行すると正確に動作してました。

WindowsとLinuxで動作に差がでるものなのでしょうか?

Aベストアンサー

#2補>
特別問題ない様に思います・
どういう動作の違いがでたんでしょうか?
文字コードに起因するものかもしれません。

Qvlookup関数で検索値を含む文字列を検索する方法

vlookup関数で例えば E1のセルに=vlookup(D1,A:C,3,false)とした場合、D1が佐藤であれば、A列に「佐藤」がある場合には当然、「佐藤」がある行の3列目の値が返されますが、「佐藤」はなく「佐藤A」や「A佐藤」がある場合にもこれらがある行の値を返して欲しいのですが、いい方法はありませんでしょうか。*を使ってできると思ったのですがうまくいきません。上記例で、=vlookup("*佐藤*",A:C,3,false)とすればできますが、*佐藤*の部分はD1の引用を利用したいのです。
 よろしくお願いします。

Aベストアンサー

=VLOOKUP("*"&D1&"*",A:C,3,FALSE)


人気Q&Aランキング