XPath

id:omochistもち - XPathでXPathのコードを書いてるのを見て、似たようなXPathを用いたノードの検索をPerlでやってみた。まぁ、うちも同じ授業うけてるわけなんだけど。

#!/usr/bin/env perl
use warnings;
use strict;
use XML::XPath;
use XML::XPath::XMLParser;
use Encode;

my ($filename, $keyword) = @ARGV;

if (!$filename || !$keyword) {
    print STDERR "usage: $0 filename keyword\n";
    exit 1;
}

my $xpath = XML::XPath->new(filename => $filename);

my $nodeset
    = $xpath->find( decode_utf8(qq{/Products/Item[Name/text()="$keyword"]/Price/text()}) );

foreach my $node ($nodeset->get_nodelist) {
    my $price = encode_utf8(XML::XPath::XMLParser::as_string($node));
    print "$keywordの価格は$price円です。\n";
}

このスクリプトは、

<Products>
    <Item>
        <Name>プログラミング Perl VOLUME1</Name>
        <Price>5300</Price>
        <Deadline>2006/10/9</Deadline>
    </Item>
</Products>

こんな感じのXMLが渡されることを想定している。実行すると、

$ perl search_by_xpath products.xml 'プログラミング Perl VOLUME1'
プログラミング Perl VOLUME1の価格は5300円です。

となる。出力がいかにも課題っぽくてアレっすね。この

/Products/Item[Name/text()="$keyword"]/Price/text()

というXPathが、

  • Products要素の子の
  • 子のName要素のテキストがkeywordであるような、Item要素の子の
  • Price要素のテキスト

を指し示してることになる。

と作ってみたものの、まぁ、たいしたこともしていないのでid:omochistのRuby版ともほとんど変わんないなー。

Plaggerでは、EntryFullText等でHTMLをXPathでextractできるようになってたりする。なので、XPathっていう仕組みは、ちょこっとだけ知ってたんだけど、結構複雑な条件付けができたりするものだったのだな。XPathの構文はすこし押さえておきたいとこだ。