File Coverage

blib/lib/XML/Struct.pm
Criterion Covered Total %
statement 27 34 79.4
branch 3 10 30.0
condition 1 3 33.3
subroutine 8 9 88.8
pod 3 4 75.0
total 42 60 70.0


line stmt bran cond sub pod time code
1             package XML::Struct;
2              
3 5     5   845919 use strict;
  5         25  
  5         168  
4 5     5   2398 use XML::LibXML::Reader;
  5         231840  
  5         509  
5 5     5   2346 use XML::Struct::Reader;
  5         19  
  5         226  
6 5     5   2423 use XML::Struct::Writer;
  5         14  
  5         158  
7 5     5   2190 use XML::Struct::Simple;
  5         14  
  5         2070  
8              
9             our $VERSION = '0.27';
10             our @ISA = qw(Exporter);
11             our @EXPORT_OK = qw(readXML writeXML simpleXML removeXMLAttr textValues);
12              
13             sub readXML { # ( [$from], %options )
14 32 50   32 1 23767 my (%options) = @_ % 2 ? (from => @_) : @_;
15              
16             my %reader_options = (
17 54         140 map { $_ => delete $options{$_} }
18 32         88 grep { exists $options{$_} }
  352         643  
19             qw(attributes whitespace path stream simple micro root ns depth content deep)
20             );
21 32 50       82 if (%options) {
22 32 50 33     163 if (exists $options{from} and keys %options == 1) {
23 32         69 $reader_options{from} = $options{from};
24             } else {
25 0         0 $reader_options{from} = \%options;
26             }
27             }
28              
29 32         820 XML::Struct::Reader->new( %reader_options )->readDocument;
30             }
31              
32             sub writeXML {
33 1     1 1 1722 my ($xml, %options) = @_;
34 1         9 XML::Struct::Writer->new(%options)->write($xml);
35             }
36              
37             sub simpleXML {
38 1     1 1 786 my ($element, %options) = @_;
39 1         10 XML::Struct::Simple->new(%options)->transform($element);
40             }
41              
42             *removeXMLAttr = *XML::Struct::Simple::removeXMLAttr;
43              
44             # TODO: document (better name?)
45             sub textValues {
46 0     0 0   my ($element, $options) = @_;
47             # TODO: %options (e.g. join => " ")
48              
49 0           my $children = $element->[2];
50 0 0         return "" if !$children;
51              
52 0           return join "", grep { $_ ne "" } map {
53 0 0         ref $_ ? textValues($_, $options) : $_
  0            
54             } @$children;
55             }
56              
57             1;
58             __END__
59              
60             =encoding utf8
61              
62             =head1 NAME
63              
64             XML-Struct - Represent XML as data structure preserving element order
65              
66             =begin markdown
67              
68             # Status
69              
70             [![Build Status](https://travis-ci.org/nichtich/XML-Struct.svg)](https://travis-ci.org/nichtich/XML-Struct)
71             [![Coverage Status](https://coveralls.io/repos/nichtich/XML-Struct/badge.svg)](https://coveralls.io/r/nichtich/XML-Struct)
72             [![Kwalitee Score](http://cpants.cpanauthors.org/dist/XML-Struct.png)](http://cpants.cpanauthors.org/dist/XML-Struct)
73              
74             =end markdown
75              
76             =head1 SYNOPSIS
77              
78             use XML::Struct qw(readXML writeXML simpleXML);
79              
80             my $xml = readXML( "input.xml" );
81             # [ root => { xmlns => 'http://example.org/' }, [ '!', [ x => {}, [42] ] ] ]
82              
83             my $doc = writeXML( $xml );
84             # <?xml version="1.0" encoding="UTF-8"?>
85             # <root xmlns="http://example.org/">!<x>42</x></root>
86              
87             my $simple = simpleXML( $xml, root => 'record' );
88             # { record => { xmlns => 'http://example.org/', x => 42 } }
89              
90             =head1 DESCRIPTION
91              
92             L<XML::Struct> implements a mapping between XML and Perl data structures. By
93             default, the mapping preserves element order, so it also suits for
94             "document-oriented" XML. In short, an XML element is represented as array
95             reference with three parts:
96              
97             [ $name => \%attributes, \@children ]
98              
99             This data structure corresponds to the abstract data model of
100             L<MicroXML|http://www.w3.org/community/microxml/>, a simplified subset of XML.
101              
102             If your XML documents don't contain relevant attributes, you can also choose
103             to map to this format:
104              
105             [ $name => \@children ] # element without attributes
106             [ $name ] # empty tag without attributes
107              
108             Both parsing (with L<XML::Struct::Reader> or function C<readXML>) and
109             serializing (with L<XML::Struct::Writer> or function C<writeXML>) are fully
110             based on L<XML::LibXML>, so performance is better than L<XML::Simple> and
111             similar to L<XML::LibXML::Simple>.
112              
113             =head1 MODULES
114              
115             =over
116              
117             =item L<XML::Struct::Reader>
118              
119             Parse XML as stream into XML data structures.
120              
121             =item L<XML::Struct::Writer>
122              
123             Write XML data structures to XML streams for serializing, SAX processing, or
124             creating a DOM object.
125              
126             =item L<XML::Struct::Writer::Stream>
127              
128             Simplified SAX handler for XML serialization.
129              
130             =item L<XML::Struct::Simple>
131              
132             Transform XML data structure into simple form.
133              
134             =back
135              
136             =head1 FUNCTIONS
137              
138             The following functions are exported on request:
139              
140             =head2 readXML( $source [, %options ] )
141              
142             Read an XML document with L<XML::Struct::Reader>. The type of source (string,
143             filename, URL, IO Handle...) is detected automatically. See
144             L<XML::Struct::Reader> for options. Options not known to XML::Struct::Reader
145             are passed to L<XML::LibXML::Reader>.
146              
147             =head2 writeXML( $xml [, %options ] )
148              
149             Write an XML document/element with L<XML::Struct::Writer>. See
150             L<XML::Struct::Writer> for options.
151              
152             =head2 simpleXML( $element [, %options ] )
153              
154             Transform an XML document/element into simple key-value format as known from
155             L<XML::Simple>. See L<XML::Struct::Simple> for options.
156              
157             =head2 removeXMLAttr( $element )
158              
159             Transform XML structure with attributes to XML structure without attributes.
160             The function does not modify the passed element but creates a modified copy.
161              
162             I<this function is deprecated and will be removed in a future release!>
163              
164             =head1 EXAMPLE
165              
166             To give an example, with L<XML::Struct::Reader>, this XML document:
167              
168             <root>
169             <foo>text</foo>
170             <bar key="value">
171             text
172             <doz/>
173             </bar>
174             </root>
175              
176             is transformed to this structure:
177              
178             [
179             "root", { }, [
180             [ "foo", { }, "text" ],
181             [ "bar", { key => "value" }, [
182             "text",
183             [ "doz", { }, [ ] ]
184             ]
185             ]
186             ]
187              
188             This module also supports a simple key-value (aka "data-oriented") format, as
189             used by L<XML::Simple>. With option C<simple> (or function C<simpleXML>) the
190             document given above would be transformed to this structure:
191              
192             {
193             foo => "text",
194             bar => {
195             key => "value",
196             doz => {}
197             }
198             }
199              
200             =head1 SEE ALSO
201              
202             This module was first created to be used in L<Catmandu::XML> and turned out to
203             also become a replacement for L<XML::Simple>. See the former for more XML
204             processing.
205              
206             L<XML::Twig> is another popular and powerfull module for stream-based
207             processing of XML documents.
208              
209             See L<XML::Smart>, L<XML::Hash::LX>, L<XML::Parser::Style::ETree>,
210             L<XML::Fast>, and L<XML::Structured> for different representations of XML data
211             as data structures (feel free to implement converters from/to XML::Struct).
212             L<XML::GenericJSON> seems to be an outdated and incomplete attempt to capture
213             more parts of XML Infoset in another data structure.
214              
215             See JSONx for a kind of reverse direction (JSON in XML).
216              
217             =head1 COPYRIGHT AND LICENSE
218              
219             This software is copyright (c) 2014 by Jakob Voß.
220              
221             This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
222              
223             =cut