• 締切済み

PerlによるXMLファイルの解析&出力

XMLファイルで以下のようなXMLファイルから、 <?xml version="1.0" encoding="Shift_JIS"?> <class3> <Personal> <No>1</No> <Name>相上男</Name> <phone>00-0000</phone> </Personal> <Personal> <No>2</No> <Name>柿句毛子</Name> <phone>11-1111</phone> </Personal> </class3> perlでNameの部分のタグだけ抜き出しXMLファイルに出力するプログラムを組み立てたいです。自分でも以下のようなプログラムを組み立てたのですが、 #!/usr/bin/perl use strict; use Encode; use XML::XPath; use XML::XPath::XMLParser; # 書き込み用にファイルを開く open( OUTPUTFILE, ">Output2.xml" ); # 標準出力に書き出し print &xml_xpath; # ファイルを出力先に設定 select( OUTPUTFILE ); # 出力先を元に戻す select( STDOUT ); # ファイルを閉じる close( OUTPUTFILE ); sub xml_xpath{ my $file = "class3.xml"; my $xp = XML::XPath->new(filename => $file); foreach my $node( $xp->find('/class3/Personal/Name')->get_nodelist){ print Encode::encode("shift_jis", $node )."\n"; } } XML::XPath::Node::Element=REF(0x1036c58c) XML::XPath::Node::Element=REF(0x1036cb8c) と、出てくるだけで動きません。ほとんど初心者なのでまったく見当違いのプログラムを組み立てているかもしれませんが、よろしくおねがいします。

みんなの回答

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

print Encode::encode("shift_jis", $node )."\n"; を print Encode::encode("shift_jis",XML::XPath::XMLParser::as_string($node))."\n"; に変更すればいいと思います。

Foolis
質問者

お礼

ありがとうございました。エラー表示が出なくなりました。 ファイル出力がまだ上手くいきませんが、この件はもう少しかんがえてみることにします。 本当にありがとうございました。

関連するQ&A

  • XML::XPath でXMLを修正して出力するには?

    XML::XPath を使って以下のようなソースを書きましたが、出力の方法がわかりません。 ++++++++++++++++ use strict; use XML::XPath; my $filename = "test.html"; my $xp = XML::XPath->new(filename=>$filename); my @nodeset = $xp->findnodes("//div[attribute::class='center']//img[attribute::class='right'"); for my $node ( @nodeset ){ print $node->removeAttribute('class'), "\n"; } print $xp; 1; ++++++++++++++++++++++++++++ 最後の print $xp のところで、修正後のXMLを出力したいです。 修正後のXMLをテキストとして出力(変数に入れるでも、標準出力でも)するには、どうすればよいのでしょうか?

    • ベストアンサー
    • Perl
  • XML::XPathを使う

    エラーがでて期待する出力が出ず困っています。 ファイル名とXPathのコマンドライン引数をとり、 指定されたパスに一致するノードを出力するものです。 (参考書の写しなので、記述ミスはないと思います。) ■grabber.pl use XML::XPath; use XML::XPath::XMLParser; my $xpath = XML::XPath->new( filename => shift @ARGV ); my $nodeset = $xpath->find( shift @ARGV ); foreach my $node ( nodeset->get_nodelist ) { print XML::XPath::XMLParser::as_string( $node ) . "\n"; } コマンドラインに入力しているものは、 perl grabber.pl data.xml "/inventory/category/item/name" ■data.xml <?xml version="1.0"?> <inventory date="2001"> <category> <item id="2"> <name>aaaa</name> </item> </category> </inventory> です。 perl grabber.pl data.xml "/inventory/category/item/name" としても、下記にエラーが出ます。 Can't locate object method "get_nodelist" via package "nodeset" (perhaps you for got to load "nodeset"?) at grabber.pl line 5. いろいろ試してみたり調べたのですが、 行き詰ってしまいました。 期待する出力は"<name>aaaa</name>"なのですが・・・ どなたかこのエラーの原因がおわかりになるかた いらっしゃいますでしょうか。 環境は以下になります。 ・windowsxp ・activePerl モジュールのインストール済み ・XML-XPath ・XML-Parser 以上です。

    • ベストアンサー
    • Perl
  • XML::XPath -- 追加したノードが見付からない

    XMLのテンプレートを既存のXMLに追加したのですが、 その後 findnodes() で検索しても合致しません。 XML::XPath::Node::Element->new() を使って作成したものは 合致してくれます。 XML::XPath::XMLParser でパースしたものを追加して findnodes() で合致させるにはどのようにしたらよいのでしょうか。 ------------------------------- use XML::XPath; #### 元のXML my $xmldata = <<EOM; <?xml version="1.0" encoding="UTF-8" ?> <list>   <item>orange</item>   <item>apple</item>   <item>lemon</item> </list> EOM ### 追加するXMLのテンプレート my $xmlappend = <<EOM;   <item>pine</item> EOM ## 追加先ノードを取り出す my $xml = XML::XPath->new( xml=>$xmldata ); my ($list) = $xml->findnodes('/list'); ## 追加用XMLを作成して追加 my $append = XML::XPath::XMLParser->new( xml=>$xmlappend )->parse; $list->appendChild( $append ); ## もういっこ追加。こちらはこの場で作る $newnode = XML::XPath::Node::Element->new('item'); $newtext = XML::XPath::Node::Text->new('banana'); $newnode->appendChild( $newtext ); $list->appendChild( $newnode ); ## 現状確認 → pine は入っていた print $list->toString."\n"; ## item一覧を取得 @nodes = $xml->findnodes('/list/item'); ## 一覧を出力 → 追加した pine が出力されない。 bananaはある。 map{ print $_->toString."\n" } @nodes;

    • ベストアンサー
    • Perl
  • [Perl]Shift-JISのXMLを解析する場

    行き詰まってしまったので教えて下さい。 <やりたいこと> とあるAPIからXMLファイルを取得し、解析して出力する、ということをやっているのですが、元のXMLがShift-JISでエンコーディングされており、これをUTF-8に変換して出力しようとしています。 <問題> XMLを取得して解析、取り出したいパラメータが出力できるようにはなったのですが、文字のエンコーディングが上手く行っていないためか、文字化けしてしまいます。 <元のXML> <?xml version="1.0" encoding="Shift_JIS"?>  <test>   <prod count=3>    <record>     <code>アイウエ</code>    </record>    <record>     <code>カキクケ-</code>    </record>    <record>     <code>ABC</code>    </record>   </prod>  </test> <XML解析用のコード> #!usr/bin/perl use utf8; use Encode qw/ from_to encode decode /; use Encode::Guess qw/ euc-jp shiftjis 7bit-jis /; use LWP::UserAgent; use XML::Simple; use Data::Dumper; #--XML取得部分省略 #--XMLはgetで$xmlに格納 $from = guess_encoding($xml)->name; &from_to($xml,$from,"utf8"); $XML::Simple::PREFFERRED_PARSER = 'XML::SAX::PurePerl'; $xs = new XML::Simple(); $ref = $xs->XMLin($xml); $xml =~ s/<\?.*\?>//; for($i=0;$i<=$#{$ref->{'test'}->{'prod'}->{'record'}};$i++){  $name = $ref->{'test'}->{'prod'}->{'record'}[$i]->{'code'}; $name = encode('utf-8',$name); print "$i : $name\n"; } <結果> 黒ダイヤに?文字で文字化けして出力される。 どなたか原因がお分かりになりますでしょうか。 よろしくお願いいたします。

  • perlとXML::Simpleの使い方

    perlを使って、下記のXMLファイルを出力したいです。 <?xml version='1.0' encoding='UTF-8' ?> <member> <No>00001</No> <Product> <ProductSeqNo>0</ProductSeqNo> <ProductName>スマートフォン</ProductName> </Product> <Product> <ProductSeqNo>3</ProductSeqNo> <ProductName>モニタ</ProductName> </Product> <RegistDate>2012/11/29</RegistDate> </member> <Product>タグの部分は、編集情報を設定するため、下記のようにプログラミングしています。 my $p = { member => [ { No => "$id", Product => {}, RegistDate => "$RegistDate" } ] }; my $AddData = { Product => { ProductSeqNo => ["$seqno"], ProductName => ["ProductName"] } }; push(@{$p->{member}}, $AddData); # データを追加 my $x = new XML::Simple; my $xml = $x->XMLout($p, NoAttr=>1, KeepRoot=>1, OutputFile => "$dir/$Details", XMLDecl => "<?xml version='1.0' encoding='UTF-8' ?>"); 上記を動かすと、以下のように出力されます。 <?xml version='1.0' encoding='UTF-8' ?> <member> <No>00001</No> <Product></Product> </member> <member> <Product> <ProductName>ProductName2</ProductName> <ProductSeqNo>1</ProductSeqNo> </Product> </member> 最初のイメージで出力する方法をご存知の方は教えて下さい。

  • vb6 XMLファイル出力について<S></S>

    vb6にてXMLファイル出力のプログラムを作成しています。 XMLファイル内容 <?xml version="1.0" encoding="UTF-8"?> <root> <key>AA</key> <string>aa</string> <key>BB</key> <string/> </root> 上記の<string/>の部分を<string></string>のように出力したいのですが、 どうしても上手くいきません。 下記にソースを記載します。 何か少しでもお分かりになる情報がありましたらご教授願いします。 よろしくお願いします。 Dim xmlDoc As MSXML2.DOMDocument 'XMLドキュメント Dim xmlPI As IXMLDOMProcessingInstruction 'XML宣言 Dim node(50) As IXMLDOMNode '要素 Dim attr As MSXML2.IXMLDOMAttribute '属性 'XMLドキュメントを作成 Set xmlDoc = New MSXML2.DOMDocument 'XML宣言を追加 Set xmlPI = xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", "version=""1.0"" encoding=""UTF-8""")) '<root>要素を追加 Set node(1) = xmlDoc.appendChild(xmlDoc.createNode(NODE_ELEMENT, "root", "")) '<key>要素を追加 Set node(2) = node(1).appendChild(xmlDoc.createNode(NODE_ELEMENT, "key", "")) node(2).Text = "AA" '<string>要素を追加 Set node(3) = node(1).appendChild(xmlDoc.createNode(NODE_ELEMENT, "string", "")) node(3).Text = "aa" '<key>要素を追加 Set node(4) = node(1).appendChild(xmlDoc.createNode(NODE_ELEMENT, "key", "")) node(4).Text = "BB" '<string>要素を追加 Set node(5) = node(1).appendChild(xmlDoc.createNode(NODE_ELEMENT, "string", "")) node(5).Text = "" 'XMLドキュメントの出力 Dim strXMLFile As String strXMLFile = Format(Date, "yyyymmdd") & Format(Time, "hhmmss") xmlDoc.save ("C:TEST\TEST.xml") '終了処理 If Not xmlDoc Is Nothing Then Set xmlDoc = Nothing If Not xmlPI Is Nothing Then Set xmlPI = Nothing

  • ->の意味

    よく->といったものが、 参考スクリプトなどをみていると、 でてくるのですが、いまいちどう 解釈してよいのやらわかりません。 調べてもなかなかみつからず、質問させていただきます。 use XML::XPath; use XML::XPath::XMLParser; my $xpath = XML::XPath->new( filename => shift @ARGV ); my $nodeset = $xpath->find( shift @ARGV ); foreach my $node ( $nodeset->get_nodelist ) { print XML::XPath::XMLParser::as_string( $node ) . "\n"; } XML::XPath->new( filename => shift @ARGV );とか $xpath->find( shift @ARGV );とか $nodeset->get_nodelistは どういった理解をすればよいのでしょうか。 教えていただけますでしょうか。

    • ベストアンサー
    • Perl
  • Perlによる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
  • ファイル出力時、ファイル名が文字化けする

    Windows上から持ってきたファイルのファイル名ををLinux上のperlプログラムでdecode(perlの内部用文字に変換)してから最終的にutf8に変換してファイル出力を行う下記プログラムがあります 下記コードの①のケースで出力したファイルの中身は文字化けしていないです。ところが②のケースで出力した場合、ファイルの中身は文字化けしていないのですがファイル名が文字化けします。 何か良い対策方法ありますでしょうか。 ------------------------------------------------------------- use utf8; use Encode qw(decode encode); $name = decode('cp932', $name); ←$nameはファイル名 $name = encode('utf8', $name); my $outpath = '/sample/test'; ← ①ファイルの中身は文字化けしていない。 my $outpath = '/sample/' . $name; ← ②ファイルの中身は文字化けしていない。ファイル名が文字化け。 opne my $fh '>', $outpath; print $fh $name; close($fh);

    • ベストアンサー
    • Perl
  • XMLによるデータ抜き出し

    http://question.excite.co.jp/kotaeru.php3?q=1880543 この質問とよく似ていますので便乗させていただきます。 上記の場合で、perlでNoと、nameタグの両方だけを抜き出したい場合、どうすればよろしいでしょうか? 出力結果をこんな感じにしたいのですが…。 <class3> <Personal> <No>1</No> <Name>相上男</Name> </Personal> <Personal> <No>1</No> <Name>柿句毛子</Name> </Personal> </class3> もしよろしければ教えてください。