[Slashdotjp-dev 412] CVS update: slashjp/Slash/XML/Atom

Back to archive index

Tatsuki SUGIURA sugi****@users*****
2006年 7月 12日 (水) 20:41:42 JST


Index: slashjp/Slash/XML/Atom/Atom.pm
diff -u /dev/null slashjp/Slash/XML/Atom/Atom.pm:1.1
--- /dev/null	Wed Jul 12 20:41:42 2006
+++ slashjp/Slash/XML/Atom/Atom.pm	Wed Jul 12 20:41:42 2006
@@ -0,0 +1,353 @@
+# This code is a part of Slash, and is released under the GPL.
+# Copyright 1997-2005 by Open Source Technology Group. See README
+# and COPYING for more information, or see http://slashcode.com/.
+# $Id: Atom.pm,v 1.1 2006/07/12 11:41:42 sugi Exp $
+
+package Slash::XML::Atom;
+
+=head1 NAME
+
+Slash::XML::Atom - Perl extension for Slash
+
+
+=head1 SYNOPSIS
+
+	use Slash::XML;
+	xmlDisplay(%data);
+
+
+=head1 DESCRIPTION
+
+LONG DESCRIPTION.
+
+
+=head1 EXPORTED FUNCTIONS
+
+=cut
+
+use strict;
+use Slash;
+use Slash::Utility;
+use XML::Parser::Expat;
+use base 'Slash::XML';
+use base 'Slash::XML::RSS';
+use vars qw($VERSION);
+
+($VERSION) = ' $Revision: 1.1 $ ' =~ /\$Revision:\s+([^\s]+)/;
+
+my %syn_ok_fields = (
+	'updateBase' => '',
+	'updateFrequency' => '',
+	'updatePeriod' => '',
+);
+
+#========================================================================
+
+=head2 create(PARAM)
+
+Creates Atom feed.
+
+=over 4
+
+=item Parameters
+
+=over 4
+
+=item PARAM
+
+Hashref of parameters.  Currently supported options are below.
+
+=over 4
+
+=item version
+
+Defaults to "1.0".
+
+=item rdfencoding
+
+Defaults to "rdfencoding" in vars.
+
+=item title
+
+Defaults to "sitename" in vars.
+
+=item description
+
+Defaults to "slogan" in vars.
+
+=item link
+
+Defaults to "absolutedir" in vars.
+
+=item date
+
+Defaults to current date.  See date2iso8601().
+
+=item subject
+
+Defaults to "rdfsubject" in vars.
+
+=item language
+
+Defaults to "rdflanguage" in vars.
+
+=item creator
+
+Defaults to "adminmail" in vars.
+
+=item publisher
+
+Defaults to "rdfpublisher" in vars.
+
+=item rights
+
+Defaults to "rdfrights" in vars.
+
+=item updatePeriod
+
+Defaults to "rdfupdateperiod" in vars.
+
+=item updateFrequency
+
+Defaults to "rdfupdatefrequency" in vars.
+
+=item updateBase
+
+Defaults to "rdfupdatebase" in vars.
+
+=item image
+
+If scalar, then just prints the default image data if scalar is true.
+If hashref, then may have "title", "url", and "link" passed.
+
+=item textinput
+
+If scalar, then just prints the default textinput data if scalar is true.
+If hashref, then may have "title", "description", "name", and "link" passed.
+
+=item items
+
+An arrayref of hashrefs.  If the "story" key of the hashref is true,
+then the item is passed to rss_story().  Otherwise, "title" and "link" must
+be defined keys, and any other single-level key may be defined
+(no multiple level hash keys).
+
+=back
+
+=back
+
+=item Return value
+
+The complete RSS data as a string.
+
+=back
+
+=cut
+
+
+sub create {
+	my($class, $param) = @_;
+	return unless exists $param->{items};
+
+	my $rss = Slash::XML::RSS->create({%$param, nocreate => 1});
+
+	return as_atom_1_0($rss);
+}
+
+# copied from as_rss_1_0 in XML::RSS ... kinda ugly, but oh well
+# http://atompub.org/2005/07/11/draft-ietf-atompub-format-10.html
+sub as_atom_1_0 {
+	my($self) = @_;
+	my($val, $output);
+
+	# XML declaration
+	$output = qq[<?xml version="1.0" encoding="$self->{encoding}"?>\n\n];
+
+	# namespaces declaration
+	$output .= qq[<feed\n xmlns="http://www.w3.org/2005/Atom"\n];
+
+	# print all imported namespaces
+	while (my($k, $v) = each %{$self->{modules}}) {
+		next if $v =~ /^(?:dc|rdf|taxo|admin)$/;
+		$output .= qq[ xmlns:$v="$k"\n];
+	}
+
+	my $lang = '';
+	if ($self->{channel}{dc}{language}) {
+		$val = $self->encode($self->{channel}{dc}{language});
+		$lang = qq[ xml:lang="$val"\n];
+	}
+
+	$output .= qq[$lang>\n\n];
+
+	# title
+	$output .= atom_encode($self, 'title', $self->{channel}{title});
+
+	# id/link
+	$val = $self->encode($self->{channel}{'link'});
+	$output .= qq[<id>$val</id>\n];
+	$output .= qq[<link href="$val"/>\n];
+
+	# self link
+	$val = '';
+	if ($self->{channel}{selflink}) {
+		$val = $self->encode($self->{channel}{selflink});
+	} elsif ($ENV{REQUEST_URI}) {
+		(my $host = $ENV{HTTP_HOST}) =~ s/:\d+$//;
+		my $scheme = defined &Slash::Apache::ConnectionIsSSL
+	        	     && Slash::Apache::ConnectionIsSSL()
+			? 'https'
+			: 'http';
+		$val = $self->encode("$scheme://$host$ENV{REQUEST_URI}");
+	}
+	$output .= qq[<link rel="self" href="$val"/>\n] if $val;
+
+	# description
+	$output .= atom_encode($self, 'subtitle', $self->{channel}{description});
+
+	# copyright
+	$val = $self->{channel}{dc}{rights} || $self->{channel}{copyright};
+	$output .= atom_encode($self, 'rights', $val);
+
+	# publication date
+	$val = $self->{channel}{dc}{date} || $self->{channel}{pubDate} || $self->{channel}{lastBuildDate};
+	$output .= atom_encode($self, 'updated', $val);
+
+	my(%author);
+	# this is specific to how Slash uses publisher and creator
+	$author{name}  = $self->{channel}{dc}{publisher} || $self->{channel}{managingEditor};
+	$author{email} = $self->{channel}{dc}{creator}   || $self->{channel}{webMaster};
+
+	if ($author{name} || $author{email}) {
+		$output .= "<author>\n";
+		for my $field (qw(name email)) {
+			$output .= ' ' . atom_encode($self, $field, $author{$field}) if $author{$field};
+		}
+		$output .= "</author>\n";
+	}
+
+	# subject
+	if ($self->{channel}{dc}{subject}) {
+		$val = $self->encode($self->{channel}{dc}{subject});
+		$output .= qq[<category term="$val"/>\n];
+	}
+
+	# Syndication module
+	foreach my $syn ( keys %syn_ok_fields ) {
+		$output .= atom_encode($self, "syn:$syn", $self->{channel}{syn}{$syn});
+	}
+
+
+
+	# Ad-hoc modules
+	while (my($url, $prefix) = each %{$self->{modules}}) {
+		next if $prefix =~ /^(dc|syn|taxo)$/;
+		while ( my($el, $value) = each %{$self->{channel}{$prefix}} ) {
+			$output .= atom_encode($self, "$prefix:$el", $value);
+		}
+  	}
+
+	if ($self->{image}{url}) {
+		$output .= atom_encode($self, 'logo', $self->{image}{url});
+	}
+
+	$output .= "\n";
+
+	################
+	# item element #
+	################
+	foreach my $item (@{$self->{items}}) {
+		if ($item->{title}) {
+			$output .= "<entry>\n";
+
+			$val = $self->encode($item->{'link'});
+			$output .= qq[<id>$val</id>\n];
+
+			$output .= atom_encode($self, 'title', $item->{title});
+
+			# $val still same as directly above
+			$output .= qq[<link href="$val"/>\n];
+
+			# XXXX if at some point we can know this is the whole text
+			# of the article, it should be "content" instead of
+			# "summary"
+			if ($item->{description}) {
+				$output .= atom_encode($self, 'summary', $item->{description});
+			}
+
+			# Dublin Core module
+			$output .= atom_encode($self, 'updated', $item->{dc}{date});
+			if ($item->{dc}{creator}) {
+				$output .= "<author>\n";
+				$output .= ' ' . atom_encode($self, 'name', $item->{dc}{creator});
+				$output .= "</author>\n";
+			}
+
+			if ($item->{dc}{subject}) {
+				$val = $self->encode($item->{dc}{subject});
+				$output .= qq[<category term="$val"/>\n];
+			}
+
+			# Ad-hoc modules
+			while (my($url, $prefix) = each %{$self->{modules}}) {
+				next if $prefix =~ /^(dc|syn|taxo)$/;
+				while ( my($el, $value) = each %{$item->{$prefix}} ) {
+					$output .= atom_encode($self, "$prefix:$el", $value);
+				}
+  			}
+
+			# end item element
+			$output .= qq[</entry>\n\n];
+		}
+
+	}
+
+    $output .= '</feed>';
+
+    return $output;
+}
+
+
+# some of this from Sam Ruby
+sub atom_encode {
+	my($self, $element, $value) = @_;
+	return '' unless $value;
+	$value = $self->encode($value);
+	# XXX make this more robust?
+	my $type = $value =~ /(?:&amp;#?\w+;|&[lg]t;)/ ? 'html' : 'text';
+
+	# try parsing.  If well formed, replace the value and type
+	if ($type eq 'html' && $value =~ /&[lg]t;/) {
+		eval {
+			my $unescaped = $value;
+			$unescaped =~ s/&lt;/</g;
+			$unescaped =~ s/&gt;/>/g;
+			$unescaped =~ s/&amp;/&/g;
+
+			my $parser = new XML::Parser::Expat;
+			$parser->parsestring("<xml>$unescaped</xml>");
+    
+			$value = qq[<div xmlns="http://www.w3.org/1999/xhtml">$unescaped</div>];
+			$type  = 'xhtml';
+		};
+	}
+
+	if ($type eq 'text') {
+		return qq[<$element>$value</$element>\n];
+	} else {
+		return qq[<$element type="$type">$value</$element>\n];
+	}
+}
+
+1;
+
+__END__
+
+
+=head1 SEE ALSO
+
+Slash(3), Slash::XML(3).
+
+=head1 VERSION
+
+$Id: Atom.pm,v 1.1 2006/07/12 11:41:42 sugi Exp $
Index: slashjp/Slash/XML/Atom/MANIFEST
diff -u /dev/null slashjp/Slash/XML/Atom/MANIFEST:1.1
--- /dev/null	Wed Jul 12 20:41:42 2006
+++ slashjp/Slash/XML/Atom/MANIFEST	Wed Jul 12 20:41:42 2006
@@ -0,0 +1,4 @@
+Atom.pm
+MANIFEST
+Makefile.PL
+test.pl
Index: slashjp/Slash/XML/Atom/Makefile.PL
diff -u /dev/null slashjp/Slash/XML/Atom/Makefile.PL:1.1
--- /dev/null	Wed Jul 12 20:41:42 2006
+++ slashjp/Slash/XML/Atom/Makefile.PL	Wed Jul 12 20:41:42 2006
@@ -0,0 +1,7 @@
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+    'NAME'	=> 'Slash::XML::Atom',
+    'VERSION_FROM' => 'Atom.pm', # finds $VERSION
+);
Index: slashjp/Slash/XML/Atom/test.pl
diff -u /dev/null slashjp/Slash/XML/Atom/test.pl:1.1
--- /dev/null	Wed Jul 12 20:41:42 2006
+++ slashjp/Slash/XML/Atom/test.pl	Wed Jul 12 20:41:42 2006
@@ -0,0 +1,20 @@
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "1..1\n"; }
+END {print "not ok 1\n" unless $loaded;}
+use Slash::XML::Atom;
+$loaded = 1;
+print "ok 1\n";
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+


Slashdotjp-dev メーリングリストの案内
Back to archive index