XML::DOM / XML::XPathで効率的なソートの方法とは?

このQ&Aのポイント
  • XML::DOM / XML::XPathを使用して効率的なソートを行う方法について教えてください。
  • 現在作成したソート方法は動作するものの効率的ではなく、またソート項目が一意のデータである必要があります。
  • XML::DOMでハッシュを使用したソート方法は通用せず、別の良い方法があるのか教えてください。
回答を見る
  • ベストアンサー

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の場合は同じようにいきません。 良い方法がありましたらお願いします。

  • dany
  • お礼率69% (29/42)
  • Perl
  • 回答数1
  • ありがとう数2

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

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

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'); foreach my $node ( sort { $a->getAttribute('id') <=> $b->getAttribute('id') } @list){ print $node->getAttribute('id')."\n"; print $node->getFirstChild->getNodeValue."\n"; }

dany
質問者

お礼

あ! そうか…それぞれのオブジェクトがもう別物なのだから $a、$bをオブジェクトに置き換えればそのままですね。 ものすごく単純な見落としをしていました。 ありがとうございます!!

関連するQ&A

  • 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
  • XML DOM XMLパーサーについて理解していません

    XMLについてイマイチ理解していないので教えてください。PHPでXMLファイルを開いて何らかの処理をするとします。例えば <?php //ドキュメントオブジェクトの作成 $doc = new DOMDocument(); //XML 文書ファイルのパース(DOM ツリーの作成) $doc->load("docs/td101.xml") //要素"b"を取得する $bElement = $doc->getElementsByTagName("b")->item(0); //取得した要素"b"に属性"ad"を設定する $bElement->setAttribute("ad","Fukuoka"); //ドキュメントをシリアライズする $doc->save("docs/result101.xml"); ?> のようにXMLファイルに属性を追加するという処理を行うとします。この時、DOMはPHPによって生成されるんでしょうか?またXMLはXMLパーサーによって解析されると本で読んだのですが、この場合PHPがXMLパーサーの機能を持っているんでしょうか?それともブラウザにXMLパーサーの機能があり、ブラウザ側で処理をされているのでしょうか?意味がわからなくて申し訳ないですが、この辺りを理解していなくて・・・御願いいたします。

    • ベストアンサー
    • XML
  • DOMでパースしているXML全体の出力方法

    お世話になります。 JavaでDOMを使ってXML操作をしたいと考えております。 おおよそ、以下のソースでparseできるところまで確認できました。 DOMParser parser = new DOMParser(); parser.parse("XMLファイルパス"); Document doc = parser.getDocument(); 開発中なので、DOM操作した結果のXMLを随時コンソールやログに 出力させたいのですが、たとえばdoc.toString()してもnullとなり、 正常に出力されません。 以下のようにElementを取得すると正常にアクセスできていることは 確認しています。 Element rootEl = doc.getDocumentElement(); System.out.println(rootEl.getNodeName()); なお、DOMライブラリにはxercesを用いております。 Dom4jのAPIも見てみましたが、それらしいメソッドを見つけることが できていません。 簡単にXMLを出力できることが理想です。 一般的な方法、よくやる手法など、みなさんよりご教示頂きたいです。

    • ベストアンサー
    • Java
  • DOMでXML操作

    PHP5でDOMを操作しXMLのタグ情報などを得たいのですがプログラムが動かないので質問させていただきました。 //test.php <?php $doc = new DomDocument; $doc->validateOnParse = true; $doc->Load('book.xml'); echo "ID が books の要素は".$doc->getElementById('books')->tagName . " です。\n"; ?> //book.xml <?xml version="1.0" encoding="shift_JIS"?> <A>   <B id="books">test</B> </A> サンプルプログラムを拾ってきてbooksのtestを取得したいのですがなかなか動きません。実行するとエラー文も何もなく「ID が books の要素は です。 」とだけ表示されます。 環境そのものが整っていないのかも解らないため詳しい方ご教授よろしくお願いします。 現在の環境です。 PHP5 Apache2.0

    • ベストアンサー
    • PHP
  • domでのXML作成について

    PHP4.2のdomを使い、下記のようなXMLを作成したいです。 しかし、Itemのノードに対して、NUMBERとNAMEという子ノードを2つつけるやり方が分からず困っています。 PHPは書いて見たのですが、上手くいっていません。 教えていただけると助かります。 宜しくお願いします。 【作成したいXML】 <Response> <Items> <Item> <NUMBER>47</NUMBER> <NAME>沖縄県</NAME> </Item> </Items> </Response> 【PHP】 $dom = domxml_new_doc("1.0"); $Response = $dom->create_element("Response"); $root = $dom->append_child($Response); $Items = $dom->create_element("Items"); $Item = $dom->create_element("Item"); $NUMBER = $dom->create_element("NAME"); $text1 = $dom->create_text_node("47"); $NUMBER->append_child($text1); $NAME = $dom->create_element("NAME"); $text2 = $dom->create_text_node("沖縄"); $NAME->append_child($text2); $Item->append_child($NAME); $Items->append_child($Item); $root->append_child($Items);

    • ベストアンサー
    • PHP
  • 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でのタグの取り出し

    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
  • XML::Parserの parsefileの結果はどんな値が正しいのでしょうか?

    PerlのXML::Parserモジュールで、Objectスタイルで パースをしようとしているのですが、 $docの値が1となり、パースの結果のデータ?は 帰ってこないのですが、何か問題があるのでしょうか? my $file = 'test.xml'; my $p = XML::Parser->new(Style=>'Object'); my $doc = $p->parsefile($file); print $doc; exit;

    • ベストアンサー
    • 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 DOMについて

    JavaScriptでDOMを使用して、xmlhttp.sendで指定のPHPファイルに送信しましたが、 PHP側で値を取得できません。 (PHP Ver.5.3.0) 以下、JavaScript var UserID="abc"; var Password="abc"; var xmlDoc = new ActiveXObject("Microsoft.XMLDom"); xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml","version=\"1.0\"")); var root = xmlDoc.createElement("xDoc"); xmlDoc.documentElement=root; var node_Item = xmlDoc.createElement("Command"); root.appendChild(node_Item); var node_UserID = xmlDoc.createElement("UserID"); node_UserID.appendChild(xmlDoc.createTextNode(UserID)), node_Item.appendChild(node_UserID); var node_Password = xmlDoc.createElement("Password"); node_Password.appendChild(xmlDoc.createTextNode(MDString(Password))), node_Item.appendChild(node_Password); var node_Sufix = xmlDoc.createElement("Sufix"); node_Sufix.appendChild(xmlDoc.createTextNode(Sufix)), node_Item.appendChild(node_Sufix); var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); xmlhttp.open("post",topURL("main/Log.php"),false); xmlhttp.send(xmlDoc); 以下、Log.php <?php session_start(); $DEBUG_MODE=false; $xmlLogQ=$_SERVER['DOCUMENT_ROOT']."/test/temp/Request.xml"; $xml = new DOMDocument(); $xml->async=false; if (!$DEBUG_MODE) { if ($XML_LOG) { $xml->save($xmlLogQ); } } else { if ($XML_LOG) { $xml->load($xmlLogQ); } } $doc=$xml->documentElement; if ($xml->parseError.errorCode==0) { $xml = $node=$doc->selectSingleNode("Command/UserID"); if (!($node==null)) { $UserID=$node->text; $node=null; } $node=$doc->selectSingleNode("Command/Sufix"); if (!($node==null)) { $Sufix=$node->text; $node=null; } $node=$doc->selectSingleNode("Command/Password"); if (!($node==null)) { $Password=$node->text; $node=null; } } ?> 保存したXML上、<?xml version="1.0"?>以降書き込みできてません。 どの部分がおかしいか不明の為、申し訳ないですがご教授お願いします。

    • ベストアンサー
    • PHP

専門家に質問してみよう