Hatena::ブログ(Diary)

koyachiの日記 このページをアンテナに追加 RSSフィード

2005/11/03

[]複数dc:subjectのRSSを読み込む、再び。XML::RSS::LibXML編

ほとんどあきらめてたXML::RSSでの複数dc:subject問題ですが、昨日の朝「下から見るエンジニアリング」を読んで惚れこんでしまったついでにXML::RSS::LibXMLソース見て、なるほど読みやすい、と思いながら眺めてたらXML::RSS::LibXMLなら少しいじるだけで複数dc:subject問題を解決できそうな気がしてきたのでいじってみました。

XML::RSS::LibXML::Parser.pmを以下のように修正してみると、

--- Parser.pm.org	2005-11-02 07:08:55.000000000 +0900
+++ Parser.pm	2005-11-03 05:47:38.759503200 +0900
@@ -219,6 +219,9 @@
         my $xpath = $prefix eq $vprefix ? 
             "./*[not(contains(name(), ':'))]" : "./*[starts-with(name(), '$prefix:')]";
 
+        # temporay nodes hash for plural node.
+        my %plural_nodes;
+
         # now, for each node that we can cover, go and parse
         foreach my $node ($xc->findnodes($xpath, $root)) {
             if ($xc->findnodes('./*', $node)) {
@@ -231,17 +234,30 @@
                     $text = '';
                 }
     
+                my $tmp_node;
                 # argh. it has attributes. we do our little hack...
                 if ($node->hasAttributes) {
-                    $sub{$node->localname} = XML::RSS::LibXML::MagicElement->new(
+                    $tmp_node = XML::RSS::LibXML::MagicElement->new(
                         content => $text,
                         attributes => [ $node->attributes ]
                     );
                 } else {
-                    $sub{$node->localname} = $text;
+                    $tmp_node = $text;
+                }
+
+                if (defined $sub{$node->localname}) {
+                    if (!defined $plural_nodes{$node->localname}) {
+                        push @{$plural_nodes{$node->localname}}, $sub{$node->localname};
+                    }
+                    push @{$plural_nodes{$node->localname}}, $tmp_node;
+                } else {
+                    $sub{$node->localname} = $tmp_node;
                 }
             }
         }
+        foreach my $key (keys %plural_nodes) {
+            $sub{$key} = $plural_nodes{$key};
+        }
 
         if (keys %sub) {
             # If this is a native RSS element, we just need to assign to

print Dumper $rssするとdc:subject部が配列になっていて成功しているようです。見やすいコードはフィードバックも得られやすいかも、と感じました。

しかし、クライアント側で複数か否かを判断するコードがダサいです。

#!/usr/local/bin/perl -w
use strict;
use warnings;
use lib "./lib";
use LWP::Simple;
use XML::RSS::LibXML;

my $url = 'http://b.hatena.ne.jp/koyachi/rss';

my $content = get( $url );
my $rss = XML::RSS::LibXML->new;

$rss->parse( $content );

my $output;
foreach my $item ( @{$rss->{items}} ) {
	$output .= "--------------------\n";
	$output .= "title : $item->{title}\n";
	$output .= "link : $item->{link}\n";
	$output .= "description : $item->{description}\n";
	
	$output .= "dc:subject : \n";
	if ( ref($item->{dc}->{subject}) eq 'ARRAY' ) {
		foreach my $subject ( @{$item->{dc}->{subject}} ) {
			$output .= "  $subject\n";
		}
	} else {
		$output .= "  $item->{dc}->{subject}";
	}
}
print $output;

というかあるときはSCALARであるときはARRAYでっていうインターフェースがダメだとは思うんだけど僕のレベルではどうすべきかわかりません。そもそもXML::RSSとの互換しつつ高速化することが目的のはずなのでその点からしてもダメですね。教えてエロイ人

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/koyachi/20051103/1130967760
記事一覧を見る / 言及キーワード一覧 / Bookmark / Playlist / About : koyachiのはてなダイヤリー RSSフィード
Error : RSSが取得できませんでした。