XML::XPathでのタグの取り出し

このQ&Aのポイント
  • perlでXMLをHTMLとTEXTに変換するために、XPathを使用して同じタグの取り出しを試みていますが、うまくいきません。具体的には、<name>タグの中身を個別に取得したいのですが、どうすればよいでしょうか?
  • perlの初心者ですが、XMLをHTMLとTEXTに変換するためにXPathを使用しています。しかし、同じタグの値を個別に取り出す方法が分かりません。特に<name>タグの値を取得したいのですが、どうすれば良いのでしょうか?
  • perlでXMLをHTMLとTEXTに変換するためにXPathを使用していますが、<name>タグの値を個別に取得する方法が分かりません。どのようにすれば、<name>タグの中身を取得できるのでしょうか?お知恵をお貸しいただけると幸いです。
回答を見る
  • ベストアンサー

XML::XPathでのタグの取り出し

perl勉強し始めの初心者ですが、よろしくお願いします。 自分なりに調べたつもりですが分からなかったので質問させていただきます。 perlでXMLをHTMLとTEXTに変換したくてParser、Simple、DOMなどを試し、最終的にXPathにたどり着きました。 でも、XPathでの同じタグの取出しができません。 -------------------------------------------- <root> <man> <name>あああ</name> <id>11111</id> <tel>111-1111</tel> </man> <man> <name>いいい</name> <id>2222</id> <tel>222-2222</tel> </man> <man> <name>ううう</name> <id>3333</id> <tel>333-3333</tel> </man> </root> -------------------------------------------- このような場合の<name>の「あああ」だけを取り出したいのですが、 "root/man/name" だと、<name>の中身が全部出てきてしまいます。 "root/man/name[1]" でもだめでした。 どなたか分かる方いらっしゃいましたら、教えてください。 よろしくお願いします。

  • Perl
  • 回答数4
  • ありがとう数5

質問者が選んだベストアンサー

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

#2> まず 指定されたXML にルートがありません。 >if($xpath->exists($jou){ 閉じカッコがありません。 >print "$xpath->findvalue($jou)\n"; のように全体を"" でくくったらちゃんと動作しないはずです。 print $xpath->findvalue($jou),"\n"; のような感じに修正下さい。 >print "$xpath->find('//jouhou/inigoukei/goutokuten')->get_node(1)\n"; 指定したパスが違っています。 そういう点を修正したものとして回答させていただくと my $node= $xpath->find('//jouhou/goukei/goutokuten')->get_node(1); の様にノードを取り出したら ノードのテキストを取り出すには $node->string_value のようにします。 分けないで $xpath->find('//jouhou/goukei/goutokuten')->get_node(1)->string_value の様にしても良いです。 ちなみに、#2のXMLの様な場合は パス指定を my $path = "//jouhou[1]/goukei/goutokuten"; のようにすれば $xpath->findvalue($path) あるいは、 $xpath->getNodeText($path) で同じデータが取り出せます。 質問文のように my $path = "//jouhou/goukei/goutokuten[1]"; と指定したら、 //jouhou/goukeiの下にある たくさんあるgoutokuten の最初という意味になって find では、 <goutokuten>3</goutokuten>←あるノード配下の最初のgoutokuten <goutokuten>4</goutokuten>←また別のノード配下の最初のgoutokuten が該当するリストということになります。

tako-kani
質問者

お礼

親切な回答ありがとうございます。 今度はうまくいきました!!

tako-kani
質問者

補足

大変お世話になりまして、ありがとうございます。 申し訳ございませんが、もう1つだけ質問させいただきたいのですが…。 もしルール違反なら、新しい質問としてあらためてさせていただきます。 --------------------------------------------------- <!-- XML文書(tensuu.xml) --> <root> <ten kai="1回">0</ten> <ten kai="2回">0</ten> <ten kai="3回">2</ten> <ten kai="4回">1</ten> : <!-- 本当はまだ続きます --> </root> --------------------------------------------------- このときの属性の"1回"を取得したいのですが、うまくいきません。 $xpath = new XML::XPath( filename => "tensuu.xml" ); #--(1)-- print $xpath->find('/root/ten/\@kai')->get_node(1)->string_value; #--(2)-- my $path = "//root/ten/\@kai[1]"; print $xpath->findvalue($path); タグと同じように試してみたのですが どちらでもエラーも出なく、無視された感じになりました。 ソースを見ると、これ以降の「 print "</p>"; 」なども出てきていません。 お手数をお掛けしますが、よければ教えていただきたいです。 よろしくお願いします。

その他の回答 (3)

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

#3>もしルール違反なら、新しい質問としてあらためてさせていただきます。 おそらく、ルール違反と言うよりマナー違反 #3>このときの属性の"1回"を取得したいのですが、うまくいきません。 他にも指定の仕方はあると思いますが、#3の場合は以下のような感じでイイかと思います。 #1番目のten の属性 kai の内容を取得する print $xpath->findvalue('/root/ten[1]/@kai'),"\n"; #属性 kai が "1回" であるノードのテキストを取得する print $xpath->findvalue('/root/ten[@kai="1回"]'),"\n";

tako-kani
質問者

お礼

ルール違反をしたにもかかわらず、回答ありがとうございました。 この方法でやってみます。 お世話になりまして、本当に感謝します。 ありがとうございました。

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

#1>XML::XPath::Node::Element=REF(0x1f116c4) と出てきてしまい… #1の回答は、ノードを取り出すものです。 おそらく、表示するためのノードからのデータの取り出し方に問題がある(オブジェクトのままになっており、表示できるデータとして取り出せていない)と思います。 よろしければ、ご使用の実際のソースを補足下さい。

tako-kani
質問者

お礼

#4のお礼の続きです。 (ルール違反でなくて)マナー違反をしたにもかかわらず、回答ありがとうございました。 と、書きたかったのです…。 間違えてしまったのでこちらに書かせていただきました。 また、質問がありましたらよろしくお願いします。 ありがとうございました。 (BLUEPIXYさんが見てくれていると良いのですが。)

tako-kani
質問者

補足

たびたび回答ありがとうございます。 よろしくお願いします。 ------------------------------------------------------------------------- もとのXML文書です---data.xml <mei> <kyuujou>ドーム</kyuujou> </mei> <jouhou> <goukei> <goutokuten>3</goutokuten> </goukei> </jouhou> <jouhou> <goukei> <goutokuten>4</goutokuten> </goukei> </jouhou> ------------------------------------------------------------------------- $xpath = new XML::XPath( filename => "./data.xml" ); #XMLの中に1つしかないタグ<kyuujou>のときこれでやっていました。 my $jou = "//mei/kyuujou"; if($xpath->exists($jou){ print "$xpath->findvalue($jou)\n"; } #教えていただいたのをやってみたものです。すでに間違っているかもしれませんが…。 my $path = "//jouhou/goukei/goutokuten"; if($xpath->exists($path)){ print "$xpath->find('//jouhou/inigoukei/goutokuten')->get_node(1)\n"; } ------------------------------------------------------------------------- これを実行するとブラウザでは 「 ドーム XML::XPath::Node::Element=REF(0x1f039e4) 」と出てしまいました。 大変申し訳ございませんが、よろしくお願いします。

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

my $node= $xp->find('/root/man/name')->get_node(1); で番号指定したノードを取り出せます。 (※番号は0始まりでなく1始まり)

tako-kani
質問者

補足

回答ありがとうございました。 試したところ、ブラウザに XML::XPath::Node::Element=REF(0x1f116c4) と出てきてしまい、いろいろ試したのですがやはり出てきません。 この場合、何が悪いのでしょうか? たびたび申し訳ございませんが、わかりましたら よろしくお願いします。

関連するQ&A

  • 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::DOM / XML::XPathでソート

    XML::DOMで効率的なソートの方法はどんなものがありますでしょうか。 一応動くものは作れたのですが、効率的とは言い難く、しかも ソート項目が一意のデータでないといけないという欠点があります。 ############################################### use XML::DOM::XPath; my $xml = <<EOM; <?xml version="1.0" encoding="UTF-8" ?> <list> <item id="10">Apple</item> <item id="5">Orange</item> <item id="20">Melon</item> </list> EOM my $parser = XML::DOM::Parser->new(); my $doc = $parser->parse( $xml ); ## <item>タグの一覧を作成 my @list = $doc->findnodes('/list/item'); ## <item>タグ id属性一覧を作成 my @idlist = map{ $_->getAttribute("id") } @list; ## id属性順にソート foreach my $id ( sort{ $a<=>$b } @idlist ){ ## id属性値を指定してノードリストを取得 my @item = $doc->findnodes('/list/item[@id='.$id.']'); ## idは一意なのでリストの先頭で固定 print $item[0]->getAttribute('id')."\n"; print $item[0]->getFirstChild->getNodeValue."\n"; } ############################################### ハッシュなら sort{ $hoe{$b} <=> $hoe{$a} } keys %hoe といった方法があるのですが、XML::DOMの場合は同じようにいきません。 良い方法がありましたらお願いします。

    • ベストアンサー
    • Perl
  • XML::LibXMLのfindnodes()で、ワイルドカードを使いたい

    XML::LibXMLでXPathを使いたいのですが、 ワイルドカードの指定がうまくいきません。 要素名に*を当てはめたいのですが、、、、 例えば以下の通りです。 下記XMLのid="1-1"とid="1-2"を抜きだしたいのです。 できればXPathにて指定したいのですが、、、 教えてください。 my $dom = $parser->parse_file($xml_file_str) or die; $x = "//Test/TestText[@id="1-*"]/text()"; $c = $dom->findnodes($x); 解析対象XML <XML> <Test> <TestText id="1-1">テスト1</TestText> <TestText id="1-2">テスト2</TestText> <TestText id="2-1">テスト3</TestText> </Test> </XML>

    • ベストアンサー
    • Perl
  • XML::XPathでのfor文の記述

    たびたびお世話になります。よろしくお願いいたします。 perlでXML文書をHTMLへ変換しています。 ---------------------------------------- <!-- file.xml --> <root> <jouhou> <mei> <toushu>あ</toushu> <toushu>い</toushu> <toushu>う</toushu> </mei> <mei> <toushu>え</toushu> <toushu>お</toushu> <toushu>か</toushu> </mei> </jouhou> </root> ---------------------------------------- このようなXMLの場合に、XML::XPathで「あ」と「え」などの最初に来る<toushu>取りたいのですが 日によって<mei>の数が異なるため、<mei>の数を取得してその数でforをすることにしました。 が、うまくいきません。 my $xp = new XML::XPath( filename => "./file.xml" ); for(my $j=1;$j<=$xp->findvalue("count(//jouhou/mei/toushu)");$j++){ print $j; #←ここでは1と2が出ます。 print $xpath->find('//jouhou/mei[$j]/toushu')->get_node(1)->string_value; } このままでは全く出なく、["$j"]とすると、出るには出るのですが「あ」が2回出てしまいます。 書き方が違うと思うのですが、()でくくってみても出ません。 ちなみに print $xpath->find('//jouhou/mei[1]/toushu')->get_node($j)->string_value; だと、ちゃんと「あ」と「い」が出ました…。 もし、お分かりになれば教えていただきたいです。 お手数をおかけしますが、よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • XML::XPathで日本語検索するには

    XML::XPathを用いてやりたいことはほぼ実現できたのですが、 いざ実装しようとしたところで最も大きな問題にぶつかってしまいました。 日本語で検索できないのです。 $xml->find('/list/item[text()="りんご"]'); エラーにはなりませんが、合致するはずのノードが出てきません。 http://kentn.at.infoseek.co.jp/xml/perl_xpath.html ↑のページを見ると対処法はあるようなのですが、 XML/XPath.pm を修正しても以下のようなエラーが表示されます。 ------------------ Query: /list/ite... ^^^ Invalid query somewhere around here (I think) ------------------ XML::XPathで日本語を扱っている方がいましたら 対処法を教えていただけませんでしょうか。 また、XML::XPath::find()で正規表現を使うことは できないのでしょうか。

    • ベストアンサー
    • Perl
  • XPathでのワイルドカード指定

    改めて質問させていただきます。 XPathで、 //Test/TestText[id="1-*"]/text() といった指定をしたいのですが、こういった 指定方法は、XPathとして正しい書き方なのでしょうか? このXPath式が与えられ、これを使ってXMLを解析 したいのですが、もしこの記法がNGの場合、 変換を加えてワイルドカードを実現したいと思います。 どのようなアプローチがベストか、教えて頂けないで しょうか? #使用言語はperlです。

  • XML:連番要素の全ての子要素にxPath式でアクセスするには

    xml文書1 <?xml version="1.0"> <customer0> <name>aaaa</name> <tel>1234</tel> </customer0> <customer1> <name>bbbb</name> <tel>2345</tel> </customer1> xml文書2 <?xml version="1.0"> <customer> <name>aaaa</name> <tel>1234</tel> </customer> <customer> <name>bbbb</name> <tel>2345</tel> </customer> xml文書1のcustomerの子要素(name,tel)を全て取得したいです。 ルートノードから辿って行くのではなく、ダイレクトにアクセスしたいです。 xPath式で子要素を全て取り出すことはできますでしょうか? xml文書2であれば「//customer」で可能だと思うんですが。 宜しくお願い致します。

    • ベストアンサー
    • XML
  • JavaScriptでXPath

    こんにちは、教えてください。 これまでVC#やVBでXMLを扱っていましたが、その際にはXPathでノードの参照することが多かったです。 今JavaScriptをやむなくいじっているのですが、JavaScriptで動的に生成したXHTMLをXPathで参照したいのですが、これは可能でしょうか? getElementByIdやgetElementsByTagName、ChildNodeなどDomでの操作用の関数がいくつかありますが、参照はこれでもいいのですが、ノードの追加や属性、テキストの追加などをやっていると、ちょっと物足りません。というかXPathが使いたいのです。どう考えてもXPathは楽です。 できるならやりたいのですが、ご存知であれば教えてください。

  • VBscriptでXMLのファイルから、XPathで指定したデータを読

    VBscriptでXMLのファイルから、XPathで指定したデータを読み込みたいと思っていますが、 XMLファイル中に指定したXPathのタグがない場合、"オブジェクトがありません。" というエラーになってしまいます。 このような場合、どのような処理にすれば良いのでしょうか?親タグ、子タグなどを総当りで、存在するか調べないといけないのでしょうか?以下のようなスクリプトです。 Set xmlDoc = WScript.CreateObject("MSXML2.DOMDocument") With xmlDoc .Async = False .Load("aaaa.xml") xpath01 = "/tag1/tag2/tag3" Set xmlNode = .selectSingleNode(xpath01) MsgBox xmlNode.text End With

  • 外部XMLでHTMLタグを使う

    Flashで読み込む外部XML内でタグを使おうとしたのですが、 上手くいきません。 <?xml version="1.0" encoding="UTF-8"?> <news> <list date="8/31">ダミーテキストです。ダミーテキストです。&lt;br&gt;ダミーテキストです。ダミーテキストです。</list> </news> のようにしたところ、そのまま<br>と表示されてしまいました。 Flash側では、 ------------------------------------------------------------- for( var i:Number=0; i<_root.dateList.length; i++){ _root.cnt.attachMovie( "news", "news"+i, 100+i ); var nNews:MovieClip = _root.cnt["news"+i]; nNews.dateField.html = true; nNews.newsField.html = true; nNews.dateField.autoSize = "left"; nNews.newsField.autoSize = "left"; nNews.dateField.htmlText = _root.dateList[i].toString(); nNews.newsField.htmlText = _root.newsList[i].toString(); } ------------------------------------------------------------- の様にしています。 ・XML の読み込みは xfactorstudio の XPath を使って読込み、 それを dateList の中に配列で格納しています。 FLASH側でHTMLを生成するのは上手くいくのですが、 外部となると、どうも・・・・。 不明点があったら、追加で記述しますので、言ってください。 どうぞ、宜しくお願いいたします。

    • ベストアンサー
    • Flash

専門家に質問してみよう