File Coverage

blib/lib/WWW/Splunk/XMLParser.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             =encoding utf8
2              
3             =head1 NAME
4              
5             WWW::Splunk::XMLParser - Parse Splunk XML format
6              
7             =head1 DESCRIPTION
8              
9             This is an utility module to deal with XML format ocassionally returned
10             by Splunk and seemlingly undocumented.
11              
12             Note that Splunk usually returns Atom XMLs, which have the same
13             content type. They can be distinguished by a DOCTYPE.
14              
15             =cut
16              
17             package WWW::Splunk::XMLParser;
18              
19 4     4   1075 use strict;
  4         22  
  4         134  
20 4     4   24 use warnings;
  4         8  
  4         132  
21              
22 4     4   3140 use XML::LibXML qw/:libxml/;
  0            
  0            
23             use Carp;
24              
25             our $VERSION = '2.07';
26              
27             =head2 B (F)
28              
29             Return a perl structure from a XML string, if it's
30             parsable, otherwise return a raw XML::LibXML object
31              
32             =cut
33              
34             sub parse {
35             my $xml = shift;
36              
37             my @tree = eval { parsetree ($xml) };
38             return $xml if $@;
39             return $#tree ? @tree : $tree[0];
40             }
41              
42             =head2 B (F)
43              
44             Parse a XML node tree recursively.
45              
46             =cut
47              
48             sub parsetree {
49             my $xml = shift;
50             my @retval;
51              
52             my $has_elements = grep { $_->nodeType eq XML_ELEMENT_NODE }
53             $xml->nonBlankChildNodes ();
54              
55             foreach my $node ($xml->nonBlankChildNodes ()) {
56              
57             # Not interested in anything but elements
58             next if $has_elements and $node->nodeType ne XML_ELEMENT_NODE;
59              
60             # Structure or structure wrapped in Atom
61             if ($node->nodeName () eq 'list' or
62             $node->nodeName () eq 's:list') {
63             push @retval, [ parsetree ($node) ];
64             } elsif ($node->nodeName () eq 'dict' or
65             $node->nodeName () eq 's:dict') {
66             push @retval, { parsetree ($node) };
67             } elsif ($node->nodeName () eq 'key' or
68             $node->nodeName () eq 's:key') {
69             push @retval, $node->getAttribute ('name')
70             => scalar parsetree($node);
71             } elsif ($node->nodeName () eq 'response' or
72             $node->nodeName () eq 'item' or
73             $node->nodeName () eq 's:item') {
74             # Basically just ignore these
75             push @retval, parsetree ($node);
76             } elsif ($node->nodeName () eq 'entry') {
77             # Crippled Atom envelope
78             foreach my $node ($node->childNodes ()) {
79             return parsetree ($node) if $node->nodeName () eq 'content';
80             }
81             } elsif ($node->nodeType eq XML_TEXT_NODE or $node->nodeName () eq '#cdata-section') {
82             return $node->textContent;
83              
84             # Results
85             } elsif ($node->nodeName () eq 'results') {
86             return map { { parsetree ($_) } }
87             grep { $_->nodeName eq 'result' }
88             $node->childNodes;
89             } elsif ($node->nodeName () eq 'field') {
90             push @retval, $node->getAttribute ('k')
91             => scalar parsetree($node);
92             } elsif ($node->nodeName () eq 'value'
93             or $node->nodeName () eq 'v') {
94             return $node->textContent;
95              
96             # Errors
97             } else {
98             die "Unknown XML element: ".$node->nodeName
99             }
100             }
101              
102             return wantarray ? @retval : $retval[0];
103             }
104              
105             =head1 SEE ALSO
106              
107             L, L, L
108              
109             =head1 AUTHORS
110              
111             Lubomir Rintel, L<< >>,
112             Michal Josef Špaček L<< >>
113              
114             The code is hosted on GitHub L.
115             Bug fixes and feature enhancements are always welcome.
116              
117             =head1 LICENSE
118              
119             This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
120              
121             =cut
122              
123             1;