File Coverage

lib/MKDoc/XML/Dumper.pm
Criterion Covered Total %
statement 192 193 99.4
branch 66 80 82.5
condition 55 74 74.3
subroutine 27 27 100.0
pod 1 20 5.0
total 341 394 86.5


line stmt bran cond sub pod time code
1             # -------------------------------------------------------------------------------------
2             # MKDoc::XML::Dumper
3             # -------------------------------------------------------------------------------------
4             # Author : Jean-Michel Hiver.
5             # Copyright : (c) MKDoc Holdings Ltd, 2003
6             #
7             # This module serializes / dumps / freezes Perl structures to a well-formed XML string
8             # and deserializes / undumps / thaws them back from XML to Perl.
9             #
10             # This module is distributed under the same license as Perl itself.
11             # -------------------------------------------------------------------------------------
12             package MKDoc::XML::Dumper;
13 5     5   194609 use MKDoc::XML::Encode;
  5         20  
  5         205  
14 5     5   2481 use MKDoc::XML::Decode;
  5         14  
  5         150  
15 5     5   2252 use MKDoc::XML::TreeBuilder;
  5         15  
  5         156  
16 5     5   34 use Scalar::Util;
  5         11  
  5         426  
17 5     5   26 use warnings;
  5         11  
  5         125  
18 5     5   26 use strict;
  5         10  
  5         200  
19              
20 5     5   28 use vars qw /$IndentLevel $BackRef/;
  5         7  
  5         37203  
21             our $Compat = 0;
22              
23             sub xml2perl
24             {
25 20     20 0 33673 my $class = shift;
26 20         44 my $xml = shift;
27 20         128 my (@tree) = MKDoc::XML::TreeBuilder->process_data ($xml);
28 20   66     463 while ( (@tree and not ref $tree[0] and $tree[0] =~ /^(\s|\n|\r)*$/) or
      66        
      33        
      33        
      66        
      66        
29 2         29 (@tree and ref $tree[0] and $tree[0]->{_tag} and $tree[0]->{_tag} eq '~pi') ) { shift (@tree) }
30              
31 20         54 local $BackRef = {};
32 20         38 local $IndentLevel = 0;
33            
34 20         111 return $class->xml_to_perl ($tree[0]);
35             }
36              
37              
38             # SECTION THAT UNDUMPS PERL FROM XML NODE
39             sub xml_to_perl
40             {
41 130     130 0 3296 my $class = shift;
42 130 100       251 @_ = map { ref $_ ? $_ : () } @_;
  318         1040  
43            
44 130 100 100     427 my @res = map {
      100        
      66        
      100        
      100        
45 130         226 $class->xml_to_perl_backwards_compat_perl_tag ($_) ||
46             $class->xml_to_perl_backref ($_) ||
47             $class->xml_to_perl_ref ($_) ||
48             $class->xml_to_perl_scalar ($_) ||
49             $class->xml_to_perl_hash ($_) ||
50             $class->xml_to_perl_array ($_) ||
51             $class->xml_to_perl_litteral ($_)
52             } @_;
53            
54 130 50       922 return pop (@res) if (@res == 1);
55 0         0 return @res;
56             }
57              
58              
59             sub xml_to_perl_backwards_compat_perl_tag
60             {
61 130     130 0 193 my ($class, $tree) = @_;
62 130 50       401 ref $tree || return ();
63 130 100       788 $tree->{_tag} eq 'perl' || return ();
64            
65 10         22 local ($Compat) = 1;
66 10         11 return $class->xml_to_perl (@{$tree->{_content}});
  10         40  
67             }
68              
69              
70             sub xml_to_perl_backref
71             {
72 122     122 0 1362 my ($class, $tree) = @_;
73 122 50       717 ref $tree || return ();
74 122 100       1261 $tree->{_tag} eq 'backref' || return ();
75 3   50     9 my $ref_id = $tree->{id} || return ();
76 3 100       14 exists $BackRef->{$ref_id} || return ();
77 2         12 return $BackRef->{$ref_id};
78             }
79              
80              
81             sub xml_to_perl_ref
82             {
83 119     119 0 1322 my ($class, $tree) = @_;
84 119 50       509 ref $tree || return ();
85 119 100       595 $tree->{_tag} eq 'ref' || return ();
86 60   50     152 my $ref_id = $tree->{id} || return ();
87            
88 60         101 my $ref = \\undef;
89 60 50       153 bless $ref, $tree->{bless} if (defined $tree->{bless});
90 60         154 $BackRef->{$ref_id} = $ref;
91            
92 60         74 ($$ref) = $class->xml_to_perl ( @{$tree->{_content}} );
  60         399  
93 60         267 return $ref;
94             }
95              
96              
97             sub xml_to_perl_scalar
98             {
99 61     61 0 2102 my ($class, $tree) = @_;
100 61 50       140 ref $tree or return ();
101 61 100       406 $tree->{_tag} eq 'scalar' or return ();
102 7 50       24 my $ref_id = $tree->{id} or return ();
103            
104 7         11 my $ref = \\undef;
105 7 100       26 bless $ref, $tree->{bless} if (defined $tree->{bless});
106 7         22 $BackRef->{$ref_id} = $ref;
107              
108 7         11 ($$ref) = $class->xml_to_perl ( @{$tree->{_content}} );
  7         35  
109 7         32 return $ref;
110             }
111              
112              
113             sub xml_to_perl_hash
114             {
115 60     60 0 12928 my ($class, $tree) = @_;
116 60 50       146 ref $tree or return ();
117 60 100       347 $tree->{_tag} eq 'hash' or return ();
118 20 50       64 my $ref_id = $tree->{id} or return ();
119              
120 20         65 my $ref = {};
121 20 100       163 bless $ref, $tree->{bless} if (defined $tree->{bless});
122 20         58 $BackRef->{$ref_id} = $ref;
123            
124 20 100       40 my @items = map { ref $_ ? $_ : () } @{$tree->{_content}};
  148         302  
  20         53  
125 20         58 foreach my $item (@items)
126             {
127 70         918 my $key = $item->{key};
128 70 100       145 if ($Compat)
129             {
130 58         57 $ref->{$key} = do {
131 58   100     178 my $stuff = $item->{_content}->[0] || '';
132 58         206 my $decode = new MKDoc::XML::Decode ('xml');
133 58         161 $decode->process ($stuff);
134             }
135             }
136             else
137             {
138 12         19 my ($val) = $class->xml_to_perl ( @{$item->{_content}} );
  12         61  
139 12         59 $ref->{$key} = $val;
140             }
141             }
142            
143 20         138 return $ref;
144             }
145              
146              
147             sub xml_to_perl_array
148             {
149 46     46 0 21430 my ($class, $tree) = @_;
150 46 50       145 ref $tree or return ();
151 46 100       271 $tree->{_tag} eq 'array' or return ();
152 13 50       52 my $ref_id = $tree->{id} or return ();
153              
154 13         30 my $ref = [];
155 13 100       47 bless $ref, $tree->{bless} if (defined $tree->{bless});
156 13         37 $BackRef->{$ref_id} = $ref;
157            
158 13 100       25 my @items = map { ref $_ ? $_ : () } @{$tree->{_content}};
  41         106  
  13         41  
159 13         40 foreach my $item (@items)
160             {
161 20         52 my $key = $item->{key};
162 20         30 my ($val) = $class->xml_to_perl ( @{$item->{_content}} );
  20         77  
163 20         65 $ref->[$key] = $val;
164             }
165            
166 13         66 return $ref;
167             }
168              
169              
170             sub xml_to_perl_litteral
171             {
172 37     37 0 2508 my ($class, $tree) = @_;
173 37 50       86 ref $tree or return ();
174 37 50       102 $tree->{_tag} eq 'litteral' or return ();
175 37 100 66     112 return undef if ($tree->{undef} and $tree->{undef} eq 'true');
176            
177 36         1305 my $decode = new MKDoc::XML::Decode ('xml');
178 36         148 return $decode->process ($tree->{_content}->[0]);
179             }
180              
181              
182             #####################################################################
183             # DUMPS PERL STRUCTURE TO XML DATA #
184             #####################################################################
185              
186              
187             sub perl2xml
188             {
189 10     10 1 35275 my $class = shift;
190 10         24 my $ref = shift;
191            
192 10         21 local $BackRef = {};
193 10         22 local $IndentLevel = 0;
194            
195 10         37 return $class->perl_to_xml ($ref);
196             }
197              
198              
199             sub perl_to_xml
200             {
201 116     116 0 2310 my ($class, $ref) = @_;
202 116   100     477 $_ = Scalar::Util::reftype ($ref) || '';
203              
204 116   66     238 return $class->perl_to_xml_backref ($ref) ||
205             $class->perl_to_xml_ref ($ref) ||
206             $class->perl_to_xml_scalar ($ref) ||
207             $class->perl_to_xml_hash ($ref) ||
208             $class->perl_to_xml_array ($ref) ||
209             $class->perl_to_xml_litteral ($ref);
210             }
211              
212              
213             sub perl_to_xml_backref
214             {
215 118     118 0 994 my ($class, $ref) = @_;
216 118 100 66     631 $ref && ref $ref || return;
217            
218 79         254 my $ref_id = 0 + $ref;
219 79 100       620 $BackRef->{$ref_id} || return;
220            
221 2         7 return $class->indent() . qq || . "\n";
222             }
223              
224              
225             sub perl_to_xml_litteral
226             {
227 43     43 0 1361 my ($class, $ref) = @_;
228 43 100       130 (defined $ref) ?
229             $class->indent() . qq || . MKDoc::XML::Encode->process ($ref) . qq || . "\n" :
230             $class->indent() . qq || . "\n";
231             }
232              
233              
234             sub perl_to_xml_scalar
235             {
236 57     57 0 1225 my ($class, $ref) = @_;
237 57 100 66     711 $ref && ref $ref && Scalar::Util::reftype ($ref) eq 'SCALAR' || return;
      100        
238            
239 7         60 my $ref_id = 0 + $ref;
240 7         22 $BackRef->{$ref_id} = $ref;
241            
242 7         19 my $bless = Scalar::Util::blessed ($ref);
243 7 100       21 $bless = ($bless) ? qq | bless="$bless"| : '';
244              
245 7         11 my $string = '';
246 7         20 $string .= $class->indent() . qq || . "\n";
247 7         22 $class->indent_more();
248 7         36 $string .= $class->perl_to_xml ($$ref);
249 7         26 $class->indent_less();
250 7         18 $string .= $class->indent() . qq || . "\n";
251            
252 7         31 return $string;
253             }
254              
255              
256             sub perl_to_xml_ref
257             {
258 115     115 0 187 my ($class, $ref) = @_;
259 115 100 66     944 $ref && ref $ref && Scalar::Util::reftype ($ref) eq 'REF' || return;
      100        
260            
261 60         91 my $ref_id = 0 + $ref;
262 60         159 $BackRef->{$ref_id} = $ref;
263            
264 60         109 my $bless = Scalar::Util::blessed ($ref);
265 60 50       104 $bless = ($bless) ? qq | bless="$bless"| : '';
266              
267 60         85 my $string = '';
268 60         146 $string .= $class->indent() . qq || . "\n";
269 60         131 $class->indent_more();
270 60         211 $string .= $class->perl_to_xml ($$ref);
271 60         171 $class->indent_less();
272 60         127 $string .= $class->indent() . qq || . "\n";
273            
274 60         1721 return $string;
275             }
276              
277              
278             sub perl_to_xml_hash
279             {
280 56     56 0 5438 my ($class, $ref) = @_;
281 56 100 66     523 $ref && ref $ref && Scalar::Util::reftype ($ref) eq 'HASH' || return;
      100        
282            
283 10         19 my $ref_id = 0 + $ref;
284 10         38 $BackRef->{$ref_id} = $ref;
285            
286 10         27 my $bless = Scalar::Util::blessed ($ref);
287 10 100       31 $bless = ($bless) ? qq | bless="$bless"| : '';
288            
289 10         17 my $string = '';
290 10         27 $string .= $class->indent() . qq || . "\n";
291 10         19 for (keys %{$ref})
  10         40  
292             {
293 12         31 $class->indent_more();
294 12         28 $string .= $class->indent() . qq || . "\n" ;
295 12         31 $class->indent_more();
296 12         36 $string .= $class->perl_to_xml ($ref->{$_});
297 12         35 $class->indent_less();
298 12         34 $string .= $class->indent() . qq || . "\n";
299 12         32 $class->indent_less();
300             }
301 10         33 $string .= $class->indent() . qq || . "\n";
302            
303 10         159 return $string;
304             }
305              
306              
307             sub perl_to_xml_array
308             {
309 52     52 0 8134 my ($class, $ref) = @_;
310 52 100 66     677 $ref && ref $ref && Scalar::Util::reftype ($ref) eq 'ARRAY' || return;
      66        
311            
312 13         26 my $ref_id = 0 + $ref;
313 13         41 $BackRef->{$ref_id} = $ref;
314            
315 13         31 my $bless = Scalar::Util::blessed ($ref);
316 13 100       38 $bless = ($bless) ? qq | bless="$bless"| : '';
317            
318 13         21 my $string = '';
319 13         35 $string .= $class->indent() . qq || . "\n";
320 13         31 for (my $i=0; $i < @{$ref}; $i++)
  39         104  
321             {
322 26         60 $class->indent_more();
323 26         156 $string .= $class->indent() . qq || . "\n" ;
324 26         63 $class->indent_more();
325 26         72 $string .= $class->perl_to_xml ($ref->[$i]);
326 26         71 $class->indent_less();
327 26         55 $string .= $class->indent() . qq || . "\n";
328 26         58 $class->indent_less();
329             }
330 13         31 $string .= $class->indent() . qq || . "\n";
331            
332 13         68 return $string;
333             }
334              
335              
336             sub indent
337             {
338 301     301 0 1333 return " " x $IndentLevel;
339             }
340              
341              
342             sub indent_more
343             {
344 144     144 0 880 $IndentLevel++;
345             }
346              
347              
348             sub indent_less
349             {
350 144     144 0 572 $IndentLevel--;
351             }
352              
353              
354             1;
355              
356              
357             __END__