File Coverage

blib/lib/XML/Smart/Tree.pm
Criterion Covered Total %
statement 371 485 76.4
branch 102 212 48.1
condition 37 71 52.1
subroutine 67 67 100.0
pod 0 7 0.0
total 577 842 68.5


line stmt bran cond sub pod time code
1             #############################################################################
2             ## Name: Tree.pm
3             ## Purpose: XML::Smart::Tree
4             ## Author: Graciliano M. P.
5             ## Modified by: Harish Madabushi
6             ## Created: 10/05/2003
7             ## RCS-ID:
8             ## Copyright: (c) 2003 Graciliano M. P.
9             ## Licence: This program is free software; you can redistribute it and/or
10             ## modify it under the same terms as Perl itself
11             #############################################################################
12              
13             package XML::Smart::Tree ;
14              
15 14     14   91 use strict ;
  14         28  
  14         604  
16 14     14   1515 use warnings ;
  11         22  
  11         330  
17              
18 14     14   85 use Carp ;
  14         170  
  14         898  
19              
20 14     14   7534 use XML::Smart::Entity qw(_parse_basic_entity) ;
  11         27  
  11         938  
21 14     14   1144 use XML::Smart::Shared qw( _unset_sig_warn _reset_sig_warn ) ;
  14         31  
  14         1258  
22              
23              
24             our ($VERSION) ;
25             $VERSION = '1.34' ;
26              
27             my %PARSERS = (
28             XML_Parser => 0 ,
29             XML_Smart_Parser => 0 ,
30             XML_Smart_HTMLParser => 0 ,
31             ) ;
32              
33             ## BUG - By making DEFAULT_LOADED a global variable it is working across objects! ( Watch for possible usage elsewhere )
34             # my $DEFAULT_LOADED ;
35              
36 14     14   1392 use vars qw($NO_XML_PARSER);
  11         17  
  11         1471  
37              
38              
39             ###################
40             # LOAD_XML_PARSER #
41             ###################
42              
43             sub load_XML_Parser {
44              
45 140 50   140 0 1635 return if $NO_XML_PARSER ;
46            
47 137         479 _unset_sig_warn() ;
48 137     9   13014 eval('use XML::Parser ;') ;
  7     9   3267  
  0     7   0  
  0     6   0  
  7     6   3665  
  0     6   0  
  0     6   0  
  5     5   2143  
  0     5   0  
  0     5   0  
  4     5   1600  
  0     5   0  
  0     5   0  
  4     5   1824  
  0     5   0  
  0     5   0  
  4     5   1599  
  0     5   0  
  0     1   0  
  4     1   1762  
  0     1   0  
  0     1   0  
  4         1677  
  0         0  
  0         0  
  4         1810  
  0         0  
  0         0  
  4         1645  
  0         0  
  0         0  
  4         1683  
  0         0  
  0         0  
  4         1751  
  0         0  
  0         0  
  4         1679  
  0         0  
  0         0  
  4         1557  
  0         0  
  0         0  
  4         1719  
  0         0  
  0         0  
  4         1744  
  0         0  
  0         0  
  4         9371  
  0         0  
  0         0  
  4         2093  
  0         0  
  0         0  
49 140         831 _reset_sig_warn() ;
50 140 50       705 if ($@) { $@ = undef ; return( undef ) ;}
  140         290  
  140         2009  
51            
52 0         0 my ($xml , $tree) ;
53            
54 0         0 _unset_sig_warn() ;
55 2         15 eval {
56 14     14   81 no strict ;
  14         24  
  14         10165  
57 2         3 my $data = '' ;
58 2         39 $xml = XML::Parser->new(Style => 'Tree') ;
59 2         1534 $tree = $xml->parse($data) ;
60             } ;
61 0         0 _reset_sig_warn() ;
62            
63 0 0 0     0 if (!$tree || ref($tree) ne 'ARRAY') { return( undef ) ;}
  2         13  
64 2 0       5 if ($tree->[1][2][0]{arg1} eq 't1') { return( 1 ) ;}
  2         43  
65 2         1100 return( undef ) ;
66              
67             }
68              
69             #########################
70             # LOAD_XML_SMART_PARSER #
71             #########################
72              
73             sub load_XML_Smart_Parser {
74              
75 133     136 0 415 _unset_sig_warn() ;
76 133     9   174354 eval('use XML::Smart::Parser ;') ;
  7     9   6710  
  7     7   18  
  7     6   188  
  7     6   43  
  7     6   17  
  7     5   104  
  5     5   28  
  5     5   9  
  5     5   71  
  4     5   23  
  4     5   7  
  4     5   54  
  4     5   23  
  4     5   9  
  4     5   62  
  4     5   21  
  4     1   12  
  4     1   52  
  4     1   33  
  4     1   9  
  4         60  
  4         22  
  4         8  
  4         56  
  4         22  
  4         8  
  4         62  
  4         21  
  4         8  
  4         58  
  4         25  
  4         9  
  4         53  
  4         23  
  4         8  
  4         63  
  4         22  
  4         8  
  4         54  
  4         22  
  4         6  
  4         56  
  4         61  
  4         11  
  4         86  
  4         24  
  4         8  
  4         62  
  4         25  
  4         8  
  4         65  
77 135         553 _reset_sig_warn() ;
78 135 50       603 if ($@) { $@ = undef ; return( undef ) ;}
  2         31  
  2         791  
79 133         519 return(1) ;
80              
81             }
82              
83             #############################
84             # LOAD_XML_SMART_HTMLPARSER #
85             #############################
86              
87             sub load_XML_Smart_HTMLParser {
88 4     7 0 21 _unset_sig_warn() ;
89 6     6   409 eval('use XML::Smart::HTMLParser ;') ;
  4         3924  
  4         14  
  4         171  
90 6         27 _reset_sig_warn() ;
91 6 50       61 if ($@) { $@ = undef ; return( undef ) ;}
  2         1179  
  0         0  
92 4         34 return(1) ;
93             }
94              
95             ########
96             # LOAD #
97             ########
98              
99             sub load {
100              
101 275     275 0 567 my ( $parser ) = @_ ;
102 275         432 my $module ;
103              
104             my $DEFAULT_LOADED ;
105              
106 275 100       910 if ($parser) {
107 146         1724 $parser =~ s/:+/_/gs ;
108 144         379 $parser =~ s/\W//g ;
109            
110 144 100       961 if ($parser =~ /^(?:html?|wild)$/i) { $parser = 'XML_Smart_HTMLParser' ;}
  16 100       39  
111 6         17 elsif ($parser =~ /^(?:re|smart)/i) { $parser = 'XML_Smart_Parser' ;}
112            
113 146         573 foreach my $Key ( keys %PARSERS ) {
114 256 100       2525 if ($Key =~ /^$parser$/i) { $module = $Key ; last ;}
  144         207  
  144         330  
115             }
116             }
117            
118 275         1535 my $ok ;
119 275 100 100     2723 if( $module && ( $module eq 'XML_Parser' ) ) {
    100 100        
    100 66        
120 6 50       50 $PARSERS{XML_Parser} = 1 if &load_XML_Parser() ;
121 6         1012 $ok = $PARSERS{XML_Parser} ;
122             } elsif ( $module && ( $module eq 'XML_Smart_Parser' ) ) {
123 118 50 33     468 $PARSERS{XML_Smart_Parser} = 1 if !$PARSERS{XML_Smart_Parser} && &load_XML_Smart_Parser() ;
124 118         251 $ok = $PARSERS{XML_Smart_Parser} ;
125             } elsif( $module and ( $module eq 'XML_Smart_HTMLParser' ) ) {
126 24 100 66     121 $PARSERS{XML_Smart_HTMLParser} = 1 if !$PARSERS{XML_Smart_HTMLParser} && &load_XML_Smart_HTMLParser() ;
127 24         51 $ok = $PARSERS{XML_Smart_HTMLParser} ;
128             }
129              
130 275 50 66     1146 if (!$ok && !$DEFAULT_LOADED) {
131 135 50       1367 $PARSERS{XML_Parser} = 1 if &load_XML_Parser() ;
132 133         249 $module = 'XML_Parser' ;
133 133 50       489 if ( !$PARSERS{XML_Parser} ) {
134 135 50       416 $PARSERS{XML_Smart_Parser} = 1 if &load_XML_Smart_Parser() ;
135 135         278 $module = 'XML_Smart_Parser' ;
136             }
137 135         240 $DEFAULT_LOADED = 1 ;
138             }
139            
140 275         1847 return($module) ;
141             }
142              
143             #########
144             # PARSE #
145             #########
146              
147             sub parse {
148              
149 185     187 0 309 my $module = $_[1] ;
150            
151 185         276 my $data ;
152             {
153 187         260 my ($fh,$open) ;
  187         278  
154            
155 187 50       1913 if (ref($_[0]) eq 'GLOB') { $fh = $_[0] ;}
  2 50       1043  
    50          
156 0         0 elsif ($_[0] =~ /^http:\/\/\w+[^\r\n]+$/s) { $data = &get_url($_[0]) ;}
157 185         313 elsif ($_[0] =~ /<.*?>/s) { $data = $_[0] ;}
158             else {
159 2 0       14 open ($fh,$_[0]) or croak( $! ); binmode($fh) ; $open = 1 ;
  2         5  
  2         35  
160             }
161            
162 187 50       1991 if ($fh) {
163 14     14   1406 no warnings ;
  11         16  
  11         8236  
164 0         0 1 while( read($fh, $data , 1024*8 , length($data) ) ) ;
165 0 0       0 close($fh) if $open ;
166             }
167             }
168            
169 187 50       856 if ($data !~ /<.*?>/s) { return( {} ) ;}
  2         4  
170            
171 187 50 33     874 if (!$module || !$PARSERS{$module}) {
172 2 0 0     1021 if ( !$NO_XML_PARSER && $INC{'XML/Parser.pm'} && $PARSERS{XML_Parser}) { $module = 'XML_Parser' ;}
  0 0 0     0  
173 0         0 elsif ($PARSERS{XML_Smart_Parser}) { $module = 'XML_Smart_Parser' ;}
174             }
175            
176 187         298 my $xml ;
177 187 50       739 if ($module eq 'XML_Parser') { $xml = XML::Parser->new() ;}
  2 100       31  
    50          
178 164         1366 elsif ($module eq 'XML_Smart_Parser') { $xml = XML::Smart::Parser->new() ;}
179 22         131 elsif ($module eq 'XML_Smart_HTMLParser') { $xml = XML::Smart::HTMLParser->new() ;}
180 0         0 else { croak("Can't find a parser for XML!") ;}
181            
182 186         317 shift(@_) ;
183 186 50 33     1642 if ( $_[0] && ( $_[0] =~ /^\s*(?:XML_\w+|html?|re\w+|smart)\s*$/i ) ) { shift(@_) ;}
  186         313  
184            
185 186         1038 _unset_sig_warn() ;
186 185         548 my ( %args ) = @_ ;
187 185         544 _reset_sig_warn() ;
188            
189 186 100       1080 if ( $args{lowtag} ) { $xml->{SMART}{tag} = 1 ;}
  2         8  
190 185 50       441 if ( $args{upertag} ) { $xml->{SMART}{tag} = 2 ;}
  1         6  
191 186 100       426 if ( $args{lowarg} ) { $xml->{SMART}{arg} = 1 ;}
  3         21  
192 186 50       893 if ( $args{uperarg} ) { $xml->{SMART}{arg} = 2 ;}
  0         0  
193 185 50       421 if ( $args{arg_single} ) { $xml->{SMART}{arg_single} = 1 ;}
  1         577  
194            
195 185 50       420 if ( $args{no_order} ) { $xml->{SMART}{no_order} = 1 ;}
  0         0  
196 186 50       412 if ( $args{no_nodes} ) { $xml->{SMART}{no_nodes} = 1 ;}
  1         1  
197            
198 186 50       416 if ( $args{use_spaces} ) { $xml->{SMART}{use_spaces} = 1 ;}
  1         457  
199            
200 185 50       512 $xml->{SMART}{on_start} = $args{on_start} if ref($args{on_start}) eq 'CODE' ;
201 185 50       457 $xml->{SMART}{on_char} = $args{on_char} if ref($args{on_char}) eq 'CODE' ;
202 186 50       499 $xml->{SMART}{on_end} = $args{on_end} if ref($args{on_end}) eq 'CODE' ;
203            
204 186         1163 $xml->setHandlers(
205             Init => \&_Init ,
206             Start => \&_Start ,
207             Char => \&_Char ,
208             End => \&_End ,
209             Final => \&_Final ,
210             ) ;
211            
212 186         335 my $tree ;
213 186         855 eval {
214 185         755 $tree = $xml->parse($data);
215 185 50       497 }; croak( $@ ) if( $@ );
216 186         1813 return( $tree ) ;
217             }
218              
219              
220              
221              
222             ##################################################
223             ## UNUSED - DEPRECATED. ##
224             ##################################################
225              
226             sub _clean_data_with_lt {
227              
228 1     2   3 my $data = shift ;
229              
230 1         20 my @data = split( //, $data ) ;
231 1         790 my $data_len = @data ;
232            
233              
234             # State Machine Definition:
235              
236 0         0 my %state_machine =
237             (
238             'in_cdata_block' => 0 ,
239             'seen_some_tag' => 0 ,
240             'need_to_cdata_this' => 0 ,
241             'prev_lt' => -1 ,
242             'last_tag_start' => -1 ,
243             'last_tag_close' => -1 ,
244             'tag_balance' => 0 ,
245             );
246            
247              
248 0         0 CHAR: for( my $index = 0; $index < $data_len; $index++ ) {
249              
250             {
251 14     14   91 no warnings ;
  14         25  
  14         39738  
  1         9  
252 1 0 0     3 next CHAR unless( $data[ $index ] eq '<' or $data[ $index ] eq '>' ) ;
253             }
254              
255 1 0       441 if( $data[ $index ] eq '<' ) {
    0          
256              
257 1 0       774 next CHAR if( $state_machine{ 'in_cdata_block' } ) ;
258            
259             {
260             # Check for possibility of this being a cdata block
261 0         0 my $possible_cdata_block = join( '', @data[ $index .. ( $index + 8 ) ] ) ;
  0         0  
262 1 0       6 if( $possible_cdata_block eq '
263 1         2 $state_machine{ 'in_cdata_block' } = 1 ;
264 1         19 next CHAR ;
265             }
266            
267             }
268              
269 1         948 $state_machine{ 'tag_balance' }++ ;
270 0         0 $state_machine{ 'prev_lt' } = $index ;
271            
272 0 0       0 next CHAR if( $state_machine{ 'need_to_cdata_this' } ) ;
273            
274 1 0       7 unless( $state_machine{ 'seen_some_tag' } ) {
275 1         3 $state_machine{ 'seen_some_tag' } = 1 ;
276 1         20 $state_machine{ 'last_tag_start' } = $index ;
277 1         471 next CHAR ;
278             }
279            
280 0 0       0 if( $state_machine{ 'tag_balance' } == 1 ) {
281 0         0 $state_machine{ 'last_tag_start' } = $index ;
282 1         7 next CHAR ;
283             }
284              
285 1         1 $state_machine{ 'need_to_cdata_this' } = 1 ;
286              
287             ## Seen a < and
288             # 1. We are not in a CDATA block
289             # 2. This is not the start of a CDATA block
290              
291              
292             } elsif( $data[ $index ] eq '>' ) {
293              
294              
295 1 0       18 if( $state_machine{ 'in_cdata_block' } ) {
296            
297 1         457 my $possible_cdata_close = join( '', @data[ ( $index - 2 ) .. $index ] ) ;
298 0 0       0 if( $possible_cdata_close eq ']]>' ) {
299 0         0 $state_machine{ 'in_cdata_block' } = 0 ;
300 1         7 $state_machine{ 'tag_balance' } = 0 ;
301 1         2 next CHAR ;
302             }
303            
304 1         16 next CHAR ;
305             }
306            
307 1 0       771 unless( $state_machine{ 'seen_some_tag' } ) {
308 0         0 croak " > found before < - Input XML seems to have errors!\n";
309             }
310              
311              
312 0         0 $state_machine{ 'tag_balance' }-- ;
313            
314 1 0       9 unless( $state_machine{ 'tag_balance' } ) {
315 1         4 $state_machine{ 'last_tag_close' } = $index ;
316 1         25 next CHAR ;
317             }
318            
319              
320             ## Need to add CDATA now.
321              
322 1         774 my $last_tag_close = $state_machine{ 'last_tag_close' } ;
323 0         0 my $prev_lt = $state_machine{ 'prev_lt' } ;
324 0         0 $data[ $last_tag_close ] = '>
325 1         9 $data[ $prev_lt ] = ']]><' ;
326              
327 1         4 $state_machine{ 'last_tag_close' } = $index ;
328 1         25 $state_machine{ 'need_to_cdata_this' } = 0 ;
329              
330 1         645 $state_machine{ 'tag_balance' } = 0 ;
331            
332             }
333              
334             }
335              
336 0         0 $data = join( '', @data ) ;
337              
338 0         0 return $data;
339              
340             }
341              
342              
343             ###########
344             # GET_URL #
345             ###########
346              
347              
348             sub get_url {
349            
350 1     2 0 5 my ( $url ) = @_ ;
351 1         2 my $data ;
352            
353 1         14 require LWP ;
354 1         402 require LWP::UserAgent ;
355              
356 0         0 my $ua = LWP::UserAgent->new();
357            
358 0         0 my $agent = $ua->agent() ;
359 1         8 $agent = "XML::Smart/$XML::Smart::VERSION $agent" ;
360 1         3 $ua->agent($agent) ;
361              
362 1         16 my $req = HTTP::Request->new(GET => $url) ;
363 0         0 my $res = $ua->request($req) ;
364              
365 0 0       0 if ($res->is_success) { return $res->content ;}
  0         0  
366 0         0 else { return undef ;}
367             }
368              
369             ##########
370             # MODULE #
371             ##########
372              
373             sub module {
374 0     2 0 0 foreach my $Key ( keys %PARSERS ) {
375 0 0       0 if ($PARSERS{$Key}) {
376 0         0 my $module = $Key ;
377 0         0 $module =~ s/_/::/g ;
378 0         0 return( $module ) ;
379             }
380             }
381 0         0 return('') ;
382             }
383              
384             #########
385             # _INIT #
386             #########
387              
388             sub _Init {
389 185     187   307 my $this = shift ;
390 185         793 $this->{PARSING}{tree} = {} ;
391 185         606 $this->{PARSING}{p} = $this->{PARSING}{tree} ;
392            
393 185         861 return ;
394             }
395              
396             ##########
397             # _START #
398             ##########
399              
400             sub _Start {
401 890     892   1046 my $this = shift ;
402            
403 890 100 100     3933 if ( $this->{LAST_CALL} && ( $this->{LAST_CALL} eq 'char' ) ) {
404 606         1510 _Char_process( $this , delete $this->{CONTENT_BUFFER} ) ;
405             }
406            
407             ##print "START>> @_\n" ;
408            
409 890         1896 $this->{LAST_CALL} = 'start' ;
410              
411 890         2483 _unset_sig_warn();
412 890         2595 my ( $tag , %args ) = @_ ;
413 890         2005 _reset_sig_warn();
414              
415 890 100 66     6125 if ( $this->{SMART}{tag} && ( $this->{SMART}{tag} == 1 ) ) { $tag = lc($tag) ;}
  10 50 33     19  
416 0         0 elsif ( $this->{SMART}{tag} && ( $this->{SMART}{tag} == 2 ) ) { $tag = uc($tag) ;}
417            
418 890 50       3644 $this->{PARSING}{p}{'/nodes'}{$tag} = 1 if !$this->{SMART}{no_nodes} ;
419            
420 890 50       2085 push( @{$this->{PARSING}{p}{'/order'}} , $tag) if !$this->{SMART}{no_order} ;
  890         2608  
421            
422 890 100       2217 if ( $this->{SMART}{arg} ) {
423 10         13 my $type = $this->{SMART}{arg} ;
424 10         10 my %argsok ;
425 10         32 foreach my $Key ( keys %args ) {
426 0         0 my $k ;
427 0 0       0 if ($type == 1) { $k = lc($Key) ;}
  0 0       0  
428 0         0 elsif ($type == 2) { $k = uc($Key) ;}
429            
430 0 0       0 if (exists $argsok{$k}) {
431 0 0       0 if ( ref $argsok{$k} ne 'ARRAY' ) {
432 0         0 my $key = $argsok{$k} ;
433 0         0 $argsok{$k} = [$key] ;
434             }
435 0         0 push(@{$argsok{$k}} , $args{$Key}) ;
  0         0  
436             }
437 0         0 else { $argsok{$k} = $args{$Key} ;}
438             }
439            
440 10         22 %args = %argsok ;
441             }
442            
443 890 50       1693 if ( $this->{SMART}{arg_single} ) {
444 0         0 foreach my $Key ( keys %args ) {
445 0 0       0 $args{$Key} = 1 if !defined $args{$Key} ;
446             }
447             }
448            
449             ## Args order:
450 890 50       1869 if ( !$this->{SMART}{no_order} ) {
451 890         993 my @order ;
452 890         2630 for(my $i = 1 ; $i < $#_ ; $i+=2) { push( @order , $_[$i] ) ;}
  858         2672  
453            
454 890 100       2021 if ( $this->{SMART}{arg} ) {
455 10         14 my $type = $this->{SMART}{arg} ;
456 10         19 foreach my $order_i ( @order ) {
457 0 0       0 if ($type == 1) { $order_i = lc($order_i) ;}
  0 0       0  
458 0         0 elsif ($type == 2) { $order_i = uc($order_i) ;}
459             }
460             }
461            
462 890 100       2246 $args{'/order'} = \@order if @order ;
463             }
464              
465 890         1995 $args{'/tag'} = $tag ;
466 890         2185 $args{'/back'} = $this->{PARSING}{p} ;
467            
468 890 50       2143 if ($this->{NOENTITY}) {
469 890         2488 foreach my $Key ( keys %args ) { &_parse_basic_entity( $args{$Key} ) ;}
  3021         7805  
470             }
471            
472 890 100       3006 if ( defined $this->{PARSING}{p}{$tag} ) {
473 282 100       965 if ( ref($this->{PARSING}{p}{$tag}) ne 'ARRAY' ) {
474 187         353 my $prev = $this->{PARSING}{p}{$tag} ;
475 187         691 $this->{PARSING}{p}{$tag} = [$prev] ;
476             }
477 282         345 push(@{$this->{PARSING}{p}{$tag}} , \%args) ;
  282         812  
478            
479 282         347 my $i = @{$this->{PARSING}{p}{$tag}} ; $i-- ;
  282         550  
  282         329  
480 282         528 $args{'/i'} = $i ;
481            
482 282         571 $this->{PARSING}{p} = \%args ;
483             }
484             else {
485 608         1535 $this->{PARSING}{p}{$tag} = \%args ;
486             ## Change the pointer:
487 608         1198 $this->{PARSING}{p} = \%args ;
488             }
489            
490 890 50       2259 if ( $this->{SMART}{on_start} ) {
491 0         0 my $sub = $this->{SMART}{on_start} ;
492 0         0 &$sub($tag , $this->{PARSING}{p} , $this->{PARSING}{p}{'/back'} , undef , $this ) ;
493             }
494            
495 890         3683 return ;
496             }
497              
498             #########
499             # _CHAR #
500             #########
501             #
502             # XML::Parser parse each line as a different call to _Char().
503             # For XML::Smart multiple calls to _Char() occurs only when the content
504             # have other nodes inside.
505             #
506              
507             sub _Char { ##print "CHAR>>\n" ;
508 1226     1228   1572 my $this = shift ;
509 1226         3281 $this->{CONTENT_BUFFER} .= $_[0] ;
510 1226         1959 $this->{LAST_CALL} = 'char' ;
511 1226         4465 return ;
512             }
513              
514             sub _Char_process {
515 1226     1228   1432 my $this = shift ;
516             ##print "CONT>> ##@_##\n" ;
517              
518 1226         8354 my $content = $_[0] ;
519            
520 1226 100 33     6673 if ( !$this->{SMART}{use_spaces} && $content !~ /\S+/s ) { return ;}
  835         1759  
521              
522             ######
523            
524 391 50 66     2186 if (! defined $this->{PARSING}{p}{'dt:dt'} && defined $this->{PARSING}{p}{'DT:DT'}) {
525 0         0 $this->{PARSING}{p}{'dt:dt'} = delete $this->{PARSING}{p}{'DT:DT'} ;
526             }
527            
528 391 100 66     1688 if ( $this->{PARSING}{p}{'dt:dt'} && ( $this->{PARSING}{p}{'dt:dt'} =~ /binary\.base64/si ) ) {
    50          
529 16         112 require XML::Smart::Base64 ;
530 16         74 $content = &XML::Smart::Base64::decode_base64($content) ;
531 16         69 delete $this->{PARSING}{p}{'dt:dt'} ;
532            
533 16 50       70 if ( $this->{PARSING}{p}{'/nodes'} ) {
534 0         0 delete $this->{PARSING}{p}{'/nodes'}{'dt:dt'} ;
535 0         0 my $nkeys = keys %{$this->{PARSING}{p}{'/nodes'}} ;
  0         0  
536 0 0       0 if ($nkeys < 1) { delete $this->{PARSING}{p}{'/nodes'} ;}
  0         0  
537             }
538            
539 16 50       70 if ( $this->{PARSING}{p}{'/order'} ) {
540 16         26 my @order = @{$this->{PARSING}{p}{'/order'}} ;
  16         67  
541 16         31 my @order_ok ;
542 16 50       34 foreach my $order_i ( @order ) { push(@order_ok , $order_i) if $order_i ne 'dt:dt' ;}
  16         61  
543 16 50       53 if (@order_ok) { $this->{PARSING}{p}{'/order'} = \@order_ok ;}
  0         0  
544 16         108 else { delete $this->{PARSING}{p}{'/order'} ;}
545             }
546             }
547 375         1056 elsif ($this->{NOENTITY}) { &_parse_basic_entity($content) ;}
548            
549             ######
550            
551 391 100       1337 if ( !exists $this->{PARSING}{p}{CONTENT} ) {
552 379         849 $this->{PARSING}{p}{CONTENT} = $content ;
553 379 50       1170 push(@{$this->{PARSING}{p}{'/order'}} , 'CONTENT') if !$this->{SMART}{no_order} ;
  379         1108  
554             }
555             else {
556 12 100       61 if ( !tied $this->{PARSING}{p}{CONTENT} ) {
557 8         21 my $cont = $this->{PARSING}{p}{CONTENT} ;
558 8         16 $this->{PARSING}{p}{CONTENT} = '' ;
559 8         80 my $tied = tie( $this->{PARSING}{p}{CONTENT} => 'XML::Smart::TieScalar' , $this->{PARSING}{p}) ;
560 8         12 push(@{$this->{TIED_CONTENTS}} , $tied) ;
  8         21  
561            
562 8         23 $this->{PARSING}{p}{'/.CONTENT/x'} = 0 ;
563 8         28 $this->{PARSING}{p}{"/.CONTENT/0"} = $cont ;
564            
565 8         10 my $cont_pos = 0 ;
566 8         11 for my $key ( @{$this->{PARSING}{p}{'/order'}} ) {
  8         24  
567 8 50       26 last if ($key eq 'CONTENT') ;
568 0         0 ++$cont_pos ;
569             }
570            
571 8 50       27 splice( @{$this->{PARSING}{p}{'/order'}} , $cont_pos,0, "/.CONTENT/0") if !$this->{SMART}{no_order} ;
  8         29  
572             }
573              
574 12         26 my $x = ++$this->{PARSING}{p}{'/.CONTENT/x'} ;
575 12         37 $this->{PARSING}{p}{"/.CONTENT/$x"} = $content ;
576 12 50       34 push( @{$this->{PARSING}{p}{'/order'}} , "/.CONTENT/$x") if !$this->{SMART}{no_order} ;
  12         36  
577             }
578            
579 391 50       1108 if ( $this->{SMART}{on_char} ) {
580 0         0 my $sub = $this->{SMART}{on_char} ;
581 0         0 &$sub($this->{PARSING}{p}{'/tag'} , $this->{PARSING}{p} , $this->{PARSING}{p}{'/back'} , \$this->{PARSING}{p}{CONTENT} , $this ) ;
582             }
583            
584 391         803 return ;
585             }
586              
587             ########
588             # _END #
589             ########
590              
591             sub _End { ##print "END>> @_[1] >> $_[0]->{PARSING}{p}{'/tag'}\n" ;
592 890     892   1277 my $this = shift ;
593            
594 890 100       2077 if ( $this->{LAST_CALL} eq 'char' ) { _Char_process( $this , delete $this->{CONTENT_BUFFER} ) ;}
  620         1574  
595 890         1473 $this->{LAST_CALL} = 'end' ;
596            
597 890         1183 my $tag = shift ;
598            
599 890 100 66     4364 if ( $this->{SMART}{tag} && ( $this->{SMART}{tag} == 1 ) ) { $tag = lc($tag) ;}
  10 50 33     18  
600 0         0 elsif ( $this->{SMART}{tag} && ( $this->{SMART}{tag} == 2 ) ) { $tag = uc($tag) ;}
601              
602 890 50       2731 if ( $this->{PARSING}{p}{'/tag'} ne $tag ) { return ;}
  0         0  
603              
604 890         1718 delete $this->{PARSING}{p}{'/tag'} ;
605            
606 890         1853 my $back = delete $this->{PARSING}{p}{'/back'} ;
607 890   100     3202 my $i = delete $this->{PARSING}{p}{'/i'} || 0 ;
608            
609 890         945 my $nkeys = keys %{$this->{PARSING}{p}} ;
  890         1557  
610            
611 890 50 33     2140 if ( $nkeys == 1 && exists $this->{PARSING}{p}{CONTENT} ) {
612 0 0       0 if (ref($back->{$tag}) eq 'ARRAY') { $back->{$tag}[$i] = $this->{PARSING}{p}{CONTENT} ;}
  0         0  
613 0         0 else { $back->{$tag} = $this->{PARSING}{p}{CONTENT} ;}
614             }
615            
616 890 50 66     2564 if ( $this->{PARSING}{p}{'/nodes'} && !%{$this->{PARSING}{p}{'/nodes'}} ) { delete $this->{PARSING}{p}{'/nodes'} ;}
  321         1129  
  0         0  
617 890 100 100     2288 if ( $this->{PARSING}{p}{'/order'} && $#{$this->{PARSING}{p}{'/order'}} <= 0 ) { delete $this->{PARSING}{p}{'/order'} ;}
  878         3215  
  487         1082  
618            
619 890         1739 delete $this->{PARSING}{p}{'/.CONTENT/x'} ;
620            
621 890 50       1934 if ( $this->{SMART}{on_end} ) {
622 0         0 my $sub = $this->{SMART}{on_end} ;
623 0         0 &$sub($tag , $this->{PARSING}{p} , $back , undef , $this) ;
624             }
625              
626 890         1204 $this->{PARSING}{p} = $back ;
627            
628 890         3796 return ;
629             }
630              
631             ##########
632             # _FINAL #
633             ##########
634              
635             sub _Final {
636 185     187   325 my $this = shift ;
637 185         390 my $tree = $this->{PARSING}{tree} ;
638            
639 185         270 foreach my $tied_cont ( @{$this->{TIED_CONTENTS}} ) {
  185         582  
640 8         35 $tied_cont->_cache_keys ;
641             }
642            
643 185         415 delete $this->{TIED_CONTENTS} ;
644 185         432 delete $this->{LAST_CALL} ;
645            
646 185         464 delete($this->{PARSING}) ;
647 185         622 return($tree) ;
648             }
649              
650             #######
651             # END #
652             #######
653              
654             1;
655              
656              
657             __END__