1 package WWW::OpenSearch::Description;
6 use base qw( Class::Accessor::Fast );
10 use WWW::OpenSearch::Url;
11 use WWW::OpenSearch::Query;
12 use WWW::OpenSearch::Image;
15 AdultContent Contact Description Developer
16 Format Image LongName Query
17 SampleSearch ShortName SyndicationRight Tags
18 Url Attribution InputEncoding OutputEncoding
22 __PACKAGE__->mk_accessors( qw( version ns ), map { lc } @columns );
26 WWW::OpenSearch::Description - Encapsulate an OpenSearch Description
27 provided by an A9 OpenSearch compatible engine
33 my $url = "http://bulkfeeds.net/opensearch.xml";
34 my $engine = WWW::OpenSearch->new($url);
35 my $description = $engine->description;
37 my $format = $description->Format; # or $description->format
38 my $longname = $description->LongName; # or $description->longname
42 WWW::OpenSearch::Description is a module designed to encapsulate an
43 OpenSearch Description provided by an A9 OpenSearch compatible engine.
44 See http://opensearch.a9.com/spec/1.1/description/ for details.
48 =head2 new( [ $xml ] )
50 Constructs a new instance of WWW::OpenSearch::Description. If scalar
51 parameter $xml is provided, data will be automatically loaded from it
58 Loads description data by parsing provided argument using XML::LibXML.
62 Return all of the urls associated with this description in an array.
64 =head2 get_best_url( )
66 Attempts to retrieve the best URL associated with this description, based
67 on the following content types (from most preferred to least preferred):
71 =item * application/atom+xml
73 =item * application/rss+xml
79 =head2 get_url_by_type( $type )
81 Retrieves the first WWW::OpenSearch::URL associated with this description
82 whose type is equal to $type.
90 =head2 AdultContent( )
102 =head2 InputEncoding( )
110 =head2 OutputEncoding( )
114 =head2 SampleSearch( )
118 =head2 SyndicationRight( )
128 =item * Tatsuhiko Miyagawa E<lt>miyagawa@bulknews.netE<gt>
130 =item * Brian Cassidy E<lt>bricas@cpan.orgE<gt>
134 =head1 COPYRIGHT AND LICENSE
136 Copyright 2007 by Tatsuhiko Miyagawa and Brian Cassidy
138 This library is free software; you can redistribute it and/or modify
139 it under the same terms as Perl itself.
153 my $self = $class->SUPER::new;
155 eval{ $self->load( $xml ); } if $xml;
157 croak "Error while parsing Description XML: $@";
167 my $parser = XML::LibXML->new;
168 my $doc = $parser->parse_string( $xml );
169 my $element = $doc->documentElement;
170 my $nodename = $element->nodeName;
172 croak "Node should be OpenSearchDescription: $nodename" if $nodename ne 'OpenSearchDescription';
174 my $ns = $element->getNamespace->value;
176 if( $ns eq 'http://a9.com/-/spec/opensearchdescription/1.0/' ) {
177 $self->ns( 'http://a9.com/-/spec/opensearchrss/1.0/' );
182 ( $version ) = $ns =~ m{([^/]+)/?$};
184 $self->version( $version );
186 for my $column ( @columns ) {
187 my $node = $doc->documentElement->getChildrenByTagName( $column ) or next;
188 if( $column eq 'Url' ) {
189 if( $version eq '1.0' ) {
190 $self->Url( [ WWW::OpenSearch::Url->new( template => $node->string_value, type => 'application/rss+xml', ns => $self->ns ) ] );
195 for my $urlnode ( $node->get_nodelist ) {
196 my $type = $urlnode->getAttributeNode( 'type' )->value;
197 my $url = $urlnode->getAttributeNode( 'template' )->value;
198 $url =~ s/\?}/}/g; # optional
199 my $method = $urlnode->getAttributeNode( 'method' );
200 $method = $method->value if $method;
203 for( $urlnode->getChildrenByTagName( 'Param' ) ) {
204 my $param = $_->getAttributeNode( 'name' )->value;
205 my $value = $_->getAttributeNode( 'value' )->value;
206 $value =~ s/\?}/}/g; # optional
207 $params{ $param } = $value;
210 push @url, WWW::OpenSearch::Url->new( template => $url, type => $type, method => $method, params => \%params, ns => $self->ns );
214 elsif( $version eq '1.1' and $column eq 'Query' ) {
215 my $queries = $self->query || [];
217 for my $node ( $node->get_nodelist ) {
218 my $query = WWW::OpenSearch::Query->new( {
219 map { $_ => $node->getAttributeNode( $_ )->value } qw( role searchTerms )
222 push @$queries, $query;
225 $self->query( $queries );
227 elsif( $version eq '1.1' and $column eq 'Image' ) {
228 my $images = $self->image || [];
230 for my $node ( $node->get_nodelist ) {
231 my $image = WWW::OpenSearch::Image->new( {
232 ( map { my $attr = $node->getAttributeNode( $_ ); $attr ? ($_ => $attr->value) : () } qw( height width type ) ),
233 url => $node->string_value
236 push @$images, $image;
239 $self->image( $images );
242 $self->$column( $node->string_value );
250 return $self->get_url_by_type( 'application/atom+xml' )
251 || $self->get_url_by_type( 'application/rss+xml' )
252 || $self->get_url_by_type( 'text/xml' )
253 || $self->url->[ 0 ];
256 sub get_url_by_type {
261 return $_ if $_->type eq $type;
269 return @{ $self->url };