File Coverage

blib/lib/XML/miniXQL.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             package XML::miniXQL;
2            
3 1     1   576 use strict;
  1         2  
  1         28  
4 1     1   5 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  1         1  
  1         66  
5            
6 1     1   422 use XML::miniXQL::Parser;
  1         2  
  1         45  
7 1     1   1246 use XML::Parser;
  0            
  0            
8            
9             require Exporter;
10            
11             @ISA = qw(Exporter);
12             @EXPORT = qw(
13             );
14            
15             $VERSION = '0.04';
16            
17            
18             sub queryXML {
19             my $param = shift;
20             my $xml;
21             if (ref $param eq 'HASH') {
22             $xml = shift;
23            
24             }
25             else {
26             $xml = $param;
27             $param = {Style => 'List'};
28             }
29            
30             my @queries = @_;
31            
32             # print "Queries:\n", join "\n", @queries;
33             # print "\n\n";
34            
35             my @Requests;
36            
37             my $req = new XML::miniXQL::Parser();
38             do {
39             $req = new XML::miniXQL::Parser(shift @queries, $req);
40             push @Requests, $req;
41             } while @queries;
42            
43             my $currenttree = new XML::miniXQL::Parser();
44            
45             my $p = new XML::Parser(Style => 'Stream',
46             _parseresults => {},
47             _currenttree => $currenttree,
48             _requests => \@Requests,
49             _style => $param->{Style},
50             );
51            
52             my $results;
53            
54             # Using exceptions for a more fine-grained control. Not completely necessary ATM though.
55             eval {
56             $results = $p->parse($xml);
57             # warn "Parse returned ", @{$results}, "\n";
58             };
59             if ($@) {
60             die $@;
61             }
62             else {
63             return $results;
64             }
65             }
66            
67             sub StartTag {
68             my $expat = shift;
69             return $expat->finish() if $expat->{_done};
70             my $element = shift;
71             # my %attribs = %_;
72            
73             #warn "Start: $element\n";
74             $expat->{_currenttree}->Append($element, %_);
75             my $current = $expat->{_currenttree};
76            
77             #warn "Path now: ", $expat->{_currenttree}->Path, "\n";
78            
79             my $removed = 0;
80            
81             foreach (0..$#{$expat->{_requests}}) {
82             next unless defined $expat->{_requests}->[$_]->Attrib;
83             # warn "Looking for attrib: ", $expat->{_requests}->[$_]->Attrib, "\n";
84             if (defined $_{$expat->{_requests}->[$_]->Attrib}) {
85             # Looking for attrib
86             if ($expat->{_requests}->[$_]->isEqual($current)) {
87             # We have equality!
88             # print "Found\n";
89             found($expat, $expat->{_requests}->[$_], $_{$expat->{_requests}->[$_]->Attrib});
90             splice(@{$expat->{_requests}}, $_ - $removed, 1) unless $expat->{_requests}->[$_]->isRepeat;
91             $expat->{_done} = 1 if (@{$expat->{_requests}} == 0);
92             $removed++;
93             # return;
94             }
95             }
96             }
97             }
98            
99             sub EndTag {
100             my $expat = shift;
101             return $expat->finish() if $expat->{_done};
102             # warn "End: $_\n";
103            
104             $expat->{_currenttree}->Pop();
105             }
106            
107             sub Text {
108             my $expat = shift;
109             my $text = $_;
110            
111             return $expat->finish() if $expat->{_done};
112            
113             my @Requests = @{$expat->{_requests}};
114             my $current = $expat->{_currenttree};
115             my $removed = 0;
116            
117             foreach (0..$#Requests) {
118             # print "(",$expat->current_element, ")Searching for: ",
119             # $Requests[$_]->Path, ($Requests[$_]->isRepeat ? "*" : ''), "\n";
120             if (!$Requests[$_]->Attrib) {
121             # Not looking for an attrib
122             # warn "Comparing : ", $Requests[$_]->Path, " : ", $expat->{_currenttree}->Path, "\n";
123             if ($Requests[$_]->isEqual($current)) {
124             # print "Found\n";
125             found($expat, $Requests[$_], $text);
126             splice(@{$expat->{_requests}}, $_ - $removed, 1) unless $Requests[$_]->isRepeat;
127             $expat->{_done} = 1 if (@Requests == 0);
128             $removed++;
129             # return;
130             }
131             }
132             }
133             }
134            
135             sub found {
136             my $expat = shift;
137             my ($request, $found) = @_;
138            
139             # warn "Found: ", $request->Path, " : $found\n";
140            
141             if ($request->Path =~ /\.\*/) {
142             # Request path contains a regexp
143             my $match = $request->Path;
144             $match =~ s/\[(.*?)\]/\\\[$1\\\]/g;
145            
146             # warn "Regexp: ", $expat->{_currenttree}->Path, " =~ |$match|\n";
147             $expat->{_currenttree}->Path =~ /$match/;
148             if ($expat->{_style} eq 'List') {
149             push @{$expat->{_parseresults}}, $&, $found;
150             }
151             elsif ($expat->{_style} eq 'Hash') {
152             push @{$expat->{_parseresults}->{$&}}, $found;
153             }
154             }
155             else {
156             if ($expat->{_style} eq 'List') {
157             push @{$expat->{_parseresults}}, $request->Path, $found;
158             }
159             elsif ($expat->{_style} eq 'Hash') {
160             push @{$expat->{_parseresults}->{$request->Path}}, $found;
161             }
162             }
163            
164             }
165            
166             sub EndDocument {
167             my $expat = shift;
168             delete $expat->{_done};
169             delete $expat->{_currenttree};
170             delete $expat->{_requests};
171             return $expat->{_parseresults};
172             }
173            
174             1;
175             __END__