File Coverage

blib/lib/Net/Amazon/MechanicalTurk/XMLParser.pm
Criterion Covered Total %
statement 28 106 26.4
branch 1 34 2.9
condition 0 6 0.0
subroutine 10 20 50.0
pod 0 9 0.0
total 39 175 22.2


line stmt bran cond sub pod time code
1             package Net::Amazon::MechanicalTurk::XMLParser;
2 20     20   693 use strict;
  20         40  
  20         583  
3 20     20   96 use warnings;
  20         1331  
  20         432  
4 20     20   88 use Carp;
  20         37  
  20         1129  
5 20     20   744 use Net::Amazon::MechanicalTurk::BaseObject;
  20         31  
  20         529  
6 20     20   11586 use Net::Amazon::MechanicalTurk::DataStructure;
  20         55  
  20         572  
7 20     20   792 use Net::Amazon::MechanicalTurk::ModuleUtil;
  20         43  
  20         414  
8 20     20   10788 use Net::Amazon::MechanicalTurk::IOUtil;
  20         61  
  20         597  
9 20     20   111 use IO::File;
  20         36  
  20         26776  
10              
11             our $VERSION = '1.00';
12              
13             our @ISA = qw{ Net::Amazon::MechanicalTurk::BaseObject };
14             our @XML_MODULES = qw{
15             XML::Parser
16             XML::Parser::Lite
17             };
18              
19             Net::Amazon::MechanicalTurk::XMLParser->attributes(qw{
20             parser
21             });
22              
23             sub init {
24 2     2 0 4 my $self = shift;
25 2 50       9 if ($#_ >= 0) {
26 0         0 $self->parser(shift);
27             }
28             else {
29 2         9 $self->parser(newParser());
30             }
31             }
32              
33             sub parseURL {
34 0     0 0 0 my ($self, $url) = @_;
35 0         0 require LWP::UserAgent;
36 0         0 my $userAgent = LWP::UserAgent->new(ssl_opts => {verify_hostname => 1});
37             # Not available on all LWP's
38             #$userAgent->default_headers->push_header("Connection" => "close");
39 0         0 my $response = $userAgent->get($url);
40 0 0       0 if (!$response->is_success) {
41 0         0 Carp::croak("Could not retrieve url $url - " . $response->status_line);
42             }
43 0         0 return $self->parse($response->content);
44             }
45              
46             sub parseFile {
47 0     0 0 0 my ($self, $file) = @_;
48 0         0 my $in = IO::File->new($file, "r");
49 0 0       0 if (!$in) {
50 0         0 Carp::croak("Could not open file $file - $!");
51             }
52 0         0 return $self->parse($in);
53             }
54              
55             sub parse {
56 0     0 0 0 my ($self, $xml) = @_;
57              
58 0 0       0 if (UNIVERSAL::isa($xml, "GLOB")) {
59 0         0 $xml = Net::Amazon::MechanicalTurk::IOUtil->readContents($xml);
60             }
61              
62 0         0 my $context = { root => undef, rootElement => undef, stack => [] };
63 0         0 my $parser = $self->newParser();
64             $parser->setHandlers(
65 0     0   0 Start => sub { $self->xmlOnStart($context, @_); },
66 0     0   0 End => sub { $self->xmlOnEnd($context, @_); },
67 0     0   0 Char => sub { $self->xmlOnChar($context, @_); }
68 0         0 );
69              
70 0         0 $parser->parse($xml);
71 0         0 my $data = Net::Amazon::MechanicalTurk::DataStructure->wrap(xmlCondenseText($context->{root}));
72              
73 0 0       0 return (wantarray) ? ($data, $context->{rootElement}) : $data;
74             }
75              
76             sub newParser {
77 2     2 0 23 return Net::Amazon::MechanicalTurk::ModuleUtil->requireFirst(@XML_MODULES)->new;
78             }
79              
80             sub xmlOnStart {
81 0     0 0   my $self = shift;
82 0           my $context = shift;
83 0           my $parser = shift;
84 0           my $element = shift;
85 0           my %attrs = @_;
86            
87 0           my $stack = $context->{stack};
88              
89 0           my $node = {};
90 0 0         if ($#${stack} >= 0) {
91 0           my $parent = $stack->[$#{$stack}];
  0            
92 0 0         if (!exists $parent->{$element}) {
93 0           $parent->{$element} = [];
94             }
95 0           push(@{$parent->{$element}}, $node);
  0            
96 0           push(@{$stack}, $node);
  0            
97             }
98             else {
99 0           $context->{root} = $node;
100 0           $context->{rootElement} = $element;
101 0           push(@{$stack}, $node);
  0            
102             }
103              
104 0 0         if (%attrs) {
105 0           while (my ($name,$value) = each %attrs) {
106 0           $self->xmlOnStart($context, $parser, $name);
107 0           $self->xmlOnChar($context, $parser, $value);
108 0           $self->xmlOnEnd($context, $parser, $name);
109             }
110             }
111             }
112              
113             sub xmlOnChar {
114 0     0 0   my ($self, $context, $parser, $text) = @_;
115 0           my $parent = $context->{stack}[$#{$context->{stack}}];
  0            
116 0 0         if (!exists $parent->{_value}) {
117 0           $parent->{_value} = $text;
118             }
119             else {
120 0           $parent->{_value} .= $text;
121             }
122             }
123              
124             sub xmlOnEnd {
125 0     0 0   my ($self, $context, $parser, $element) = @_;
126 0           pop(@{$context->{stack}});
  0            
127             }
128              
129             sub xmlCondenseText {
130 0     0 0   my ($node) = @_;
131              
132 0 0         return unless defined ($node);
133              
134 0           while (my ($name, $array) = each(%$node)) {
135 0 0         if ($name eq "_value") {
136 0 0         if ($array =~ /^\s*$/) {
137 0           delete $node->{$name};
138             }
139 0           next;
140             }
141              
142 0 0         next unless UNIVERSAL::isa($array, "ARRAY");
143              
144 0           for (my $i=0; $i<=$#{$array}; $i++) {
  0            
145 0           my $subNode = $array->[$i];
146 0 0         if (UNIVERSAL::isa($subNode, 'HASH')) {
147 0 0 0       if (exists $subNode->{_value} and $subNode->{_value} =~ /^\s*$/) {
148 0           delete $subNode->{_value};
149             }
150 0 0 0       if (exists $subNode->{_value} and (scalar keys %$subNode) == 1) {
    0          
151 0           $array->[$i] = $subNode->{_value};
152             }
153             elsif ((scalar keys %$subNode) == 0) {
154 0           $array->[$i] = undef;
155             }
156             else {
157 0           xmlCondenseText($subNode);
158             }
159             }
160             }
161             }
162              
163 0           return $node;
164             }
165              
166             return 1;