File Coverage

blib/lib/WWW/Mechanize/XML.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package WWW::Mechanize::XML;
2              
3 1     1   868 use vars qw( $VERSION );
  1         2  
  1         52  
4             $VERSION = '0.02';
5              
6 1     1   5 use strict;
  1         2  
  1         35  
7 1     1   18 use warnings;
  1         1  
  1         30  
8              
9 1     1   5 use base qw( WWW::Mechanize );
  1         1  
  1         1201  
10              
11 1     1   219897 use XML::LibXML;
  0            
  0            
12             use File::Temp qw( tempfile );
13              
14             =head1 NAME
15              
16             WWW::Mechanize::XML - adds an XML DOM accessor to L.
17              
18             =head1 VERSION
19              
20             This document describes WWW::Mechanize::XML version 0.02
21              
22             =head1 SYNOPSIS
23              
24             use WWW::Mechanize::XML;
25             use Test::More;
26             my $mech = WWW::Mechanize::XML->new();
27            
28             ok($mech->get('http://flickr.com/service/?method=getPhotos'), 'got photo list');
29             lives_ok {
30             $dom = $mech->xml();
31             } 'got xml dom object';
32             $root = $dom->domumentElement();
33             my @photos = $root->findnodes('/rsp/photos/photo');
34             is(scalar @photos, 23, 'got 23 photos');
35              
36             =head1 DESCRIPTION
37              
38             This is a subclass of L that provides an XML DOM accessor which
39             parses the contents of the response and returns it as a
40             L. The motivation for developing this module was to
41             facilitate testing of XML APIs and XHTML web pages.
42              
43             =head1 METHODS
44              
45             =head2 new( %options )
46              
47             Creates a new C object with the specified options. This
48             constructor method accepts all of the arguments accepted by L -
49             see L for further details. Other optional arguments accepted by
50             this method are C and C:
51              
52             =head3 xml_parser_options
53              
54             This argument, if specified, must be a hashref of valid L
55             options which will be used to instantiate the XML parser. If no parser options
56             are specified defaults are used. Please see the documentation for
57             L for option descriptions and default values. Valid parser
58             options accepted are:
59              
60             =over
61              
62             =item validation
63              
64             =item recover
65              
66             =item recover_silently
67              
68             =item expand_entities
69              
70             =item keep_blanks
71              
72             =item pedantic_parser
73              
74             =item line_numbers
75              
76             =item load_ext_dtd
77              
78             =item complete_attributes
79              
80             =item expand_xinclude
81              
82             =item clean_namespaces
83              
84             =back
85              
86             =head3 xml_error_options
87              
88             This argument, if specified, must be a hashref containing at least the
89             C key. If there is a value for the given xpath expression it will
90             cause the call to C to die with that value. If a C key is
91             specified the call will only die if the value at C equals
92             C. If a C key is specified the call to C
93             will die with the value at that path.
94              
95             =cut
96              
97             my @valid_parser_options = qw(
98             validation
99             recover
100             recover_silently
101             expand_entities
102             keep_blanks
103             pedantic_parser
104             line_numbers
105             load_ext_dtd
106             complete_attributes
107             expand_xinclude
108             clean_namespaces
109             );
110              
111             sub new {
112             my ( $class, %args ) = @_;
113            
114             # check for 'parser_options' for backwards compatability
115             my $parser_options =
116             delete $args{xml_parser_options} || delete $args{parser_options} || {};
117             unless (ref $parser_options eq 'HASH') {
118             die "'xml_parser_options' must be a hash-ref" ;
119             }
120            
121             my $error_options = delete $args{xml_error_options} || {};
122             unless (ref $error_options eq 'HASH') {
123             die "'xml_error_options' must be a hash-ref" ;
124             }
125            
126             # use catalog to speed up parsing if DTD is loaded
127             my ( $catalog_fh, $catalog_file ) = tempfile();
128             my $parser = XML::LibXML->new();
129             $parser->load_catalog( $catalog_file );
130            
131             # set each parser option is valid
132             foreach my $option (keys %$parser_options) {
133             if (grep { $_ =~ $option } @valid_parser_options) {
134             $parser->$option( $parser_options->{$option} );
135             } else {
136             die "Invalid parser option: $option";
137             }
138             }
139            
140             my $self = bless WWW::Mechanize->SUPER::new( %args ), $class;
141             $self->{xml_parser} = $parser;
142             $self->{xml_error_options} = $error_options;
143             return $self;
144             }
145              
146             =head2 xml( )
147              
148             Returns a L object created from the response content by
149             calling the L parse_string() method. Any parsing errors
150             will propogate up. If C were specified for this instance
151             the response document is check for errors accordingly - this method will die
152             if errors are found in the document as specified by the options.
153              
154             =cut
155              
156             sub xml {
157             my $self = shift;
158            
159             my $dom = $self->{xml_parser}->parse_string( $self->content() );
160             $dom->indexElements(); # speed up XPath queries for static documents
161            
162             # if a trigger_xpath is set check for error
163             if ($self->{xml_error_options}->{trigger_xpath}) {
164             my $root = $dom->documentElement();
165             my $error = $root->findvalue($self->{xml_error_options}->{trigger_xpath});
166            
167             # if error found at trigger_xpath...
168             if ($error) {
169            
170             # if trigger_value is specified only die if the error has that value
171             my $tv = $self->{xml_error_options}->{trigger_value};
172             return $dom if ($tv && $tv ne $error);
173            
174             # if message_xpath is specified die with the value at that location
175             if ($self->{xml_error_options}->{message_xpath}) {
176             die $root->findvalue($self->{xml_error_options}->{message_xpath});
177             }
178            
179             die $error;
180             }
181             }
182            
183             return $dom;
184             }
185              
186             =head1 DEPENDENCIES
187              
188             L
189             L
190             L
191              
192             =head1 BUGS
193              
194             Please report any bugs you find via the CPAN RT system.
195              
196             =head1 COPYRIGHT
197              
198             Copyright Fotango 2006. All rights reserved.
199              
200             This module is free software; you can redistribute it and/or modify it under
201             the same terms as Perl itself.
202              
203             =head1 AUTHOR
204              
205             Barry White
206              
207             =cut
208              
209             1;
210              
211             __END__