File Coverage

blib/lib/XML/XSH2/LibXMLCompat.pm
Criterion Covered Total %
statement 110 265 41.5
branch 19 94 20.2
condition 2 45 4.4
subroutine 35 60 58.3
pod 1 47 2.1
total 167 511 32.6


line stmt bran cond sub pod time code
1             # -*- cperl -*-
2             # $Id: LibXMLCompat.pm,v 2.5 2007-04-02 13:19:55 pajas Exp $
3              
4             package XML::XSH2::LibXMLCompat;
5              
6 8     8   57 use strict;
  8         18  
  8         256  
7 8     8   5443 use XML::LibXML;
  8         350176  
  8         63  
8 8     8   1285 use XML::LibXML::Iterator;
  8         24  
  8         236  
9 8     8   46 use XML::LibXML::NodeList;
  8         22  
  8         187  
10 8     8   43 use vars qw($VERSION);
  8         21  
  8         17654  
11              
12             $VERSION='2.2.9'; # VERSION TEMPLATE
13              
14             sub module {
15 15     15 0 54 return "XML::LibXML";
16             }
17              
18             sub version {
19 0     0 0 0 return $XML::LibXML::VERSION;
20             }
21              
22             sub toStringUTF8 {
23 43     43 0 162 my ($class,$node,$mode)=@_;
24 43 50       136 return unless $node;
25 43 100       289 $mode = 0 unless $mode;
26 43 100       171 if ($class->is_document($node)) {
    50          
    50          
27 9         210 return XML::LibXML::encodeToUTF8($node->getEncoding(),$node->toString($mode));
28             } elsif ($class->is_namespace($node)) {
29 0 0       0 return 'xmlns'.($node->name() ne '' ? ':' : '').
30             $node->name()."='".$node->getNamespaceURI()."'";
31             } elsif ($class->is_attribute($node)) {
32 0         0 return $node->name()."='".$node->value()."'";
33             } else {
34 34 50       942 return $node->can('toString') ?
35             $node->toString($mode) :
36             $node->to_literal();
37             }
38             }
39              
40             sub new_parser {
41 15     15 0 71 return XML::LibXML->new();
42             }
43              
44             sub owner_document {
45 294     294 0 821 my ($self,$node)=@_;
46 294 100       752 if ($self->is_document($node)) {
47 12         97 return $node
48             } else {
49 282         1710 return $node->ownerDocument()
50             }
51             }
52              
53             sub doc_URI {
54 0     0 0 0 my ($class,$dom)=@_;
55 0         0 return $dom->URI();
56             }
57              
58             sub doc_encoding {
59 0     0 0 0 my ($class,$dom)=@_;
60 0         0 return $dom->getEncoding();
61             }
62              
63             sub set_encoding {
64 0     0 0 0 my ($class,$dom,$encoding)=@_;
65 0         0 return $dom->setEncoding($encoding);
66             }
67              
68             sub xml_equal {
69 224     224 0 689 my ($class,$a,$b)=@_;
70 224         1130 return $a->isSameNode($b);
71             }
72              
73             sub doc_process_xinclude {
74 0     0 0 0 my ($class,$parser,$doc)=@_;
75 0         0 $parser->processXIncludes($doc);
76             }
77              
78             sub init_parser {
79 54     54 0 134 my ($class,$parser)=@_;
80 54         338 $parser->validation(0+$XML::XSH2::Functions::VALIDATION);
81 54 50       1243 $parser->recover(0+$XML::XSH2::Functions::RECOVERING) if $parser->can('recover');
82 54         931 $parser->expand_entities(0+$XML::XSH2::Functions::PARSER_EXPANDS_ENTITIES);
83 54         821 $parser->keep_blanks(0+$XML::XSH2::Functions::KEEP_BLANKS);
84 54         1282 $parser->pedantic_parser(0+$XML::XSH2::Functions::PEDANTIC_PARSER);
85 54         690 $parser->load_ext_dtd(0+$XML::XSH2::Functions::LOAD_EXT_DTD);
86 54         633 $parser->complete_attributes(0+$XML::XSH2::Functions::PARSER_COMPLETES_ATTRIBUTES);
87 54         625 $parser->expand_xinclude(0+$XML::XSH2::Functions::PARSER_EXPANDS_XINCLUDE);
88 54 50       653 if ($parser->can('line_numbers')) {
89 54         169 $parser->line_numbers(0+$XML::XSH2::Functions::LINE_NUMBERS);
90             }
91             }
92              
93             sub load_catalog {
94 0     0 0 0 my ($class,$parser,$catalog)=@_;
95 0         0 $parser->load_catalog($catalog);
96             }
97              
98             sub parse_chunk {
99 0     0 0 0 my ($class,$parser,$str)=@_;
100 0         0 $class->init_parser($parser);
101 0         0 return $parser->parse_xml_chunk($str);
102             }
103              
104             sub parse_string {
105 53     53 0 146 my ($class,$parser,$str)=@_;
106 53         192 $class->init_parser($parser);
107 53         466 return $parser->parse_string($str);
108             }
109              
110             sub parse_html_file {
111 0     0 0 0 my ($class,$parser,$file)=@_;
112 0         0 $class->init_parser($parser);
113 0         0 my $doc=$parser->parse_html_file($file);
114 0         0 return $doc;
115             }
116              
117             sub parse_html_fh {
118 0     0 0 0 my ($class,$parser,$fh)=@_;
119 0         0 $class->init_parser($parser);
120 0         0 my $doc=$parser->parse_html_fh($fh);
121 0         0 return $doc;
122             }
123              
124             sub parse_html_string {
125 0     0 0 0 my ($class,$parser,$file)=@_;
126 0         0 $class->init_parser($parser);
127 0         0 my $doc=$parser->parse_html_string($file);
128 0         0 return $doc;
129             }
130              
131             sub parse_sgml_file {
132 0     0 0 0 my ($class,$parser,$file,$encoding)=@_;
133 0         0 $class->init_parser($parser);
134 0         0 my $doc=$parser->parse_sgml_file($file,$encoding);
135 0         0 return $doc;
136             }
137              
138             sub parse_sgml_fh {
139 0     0 0 0 my ($class,$parser,$fh,$encoding)=@_;
140 0         0 $class->init_parser($parser);
141 0         0 my $doc=$parser->parse_sgml_fh($fh,$encoding);
142 0         0 return $doc;
143             }
144              
145             sub parse_sgml_string {
146 0     0 0 0 my ($class,$parser,$fh,$encoding)=@_;
147 0         0 $class->init_parser($parser);
148 0         0 my $doc=$parser->parse_sgml_string($fh,$encoding);
149 0         0 return $doc;
150             }
151              
152             sub parse_fh {
153 0     0 0 0 my ($class,$parser,$fh)=@_;
154 0         0 $class->init_parser($parser);
155 0         0 return $parser->parse_fh($fh);
156             }
157              
158             sub parse_file {
159 1     1 0 4 my ($class,$parser,$file)=@_;
160 1         5 $class->init_parser($parser);
161 1         11 return $parser->parse_file($file);
162             }
163              
164             sub is_node {
165 0     0 0 0 my ($class,$node)=@_;
166 0   0     0 return ref($node) && $node->isa('XML::LibXML::Node');
167             }
168              
169             sub is_dtd {
170 0     0 0 0 my ($class,$node)=@_;
171 0         0 return $node->nodeType == XML::LibXML::XML_DTD_NODE()
172             }
173              
174             sub is_xinclude_start {
175 0     0 0 0 my ($class,$node)=@_;
176 0         0 return $node->nodeType == XML::LibXML::XML_XINCLUDE_START();
177             }
178              
179             sub is_xinclude_end {
180 0     0 0 0 my ($class,$node)=@_;
181 0         0 return $node->nodeType == XML::LibXML::XML_XINCLUDE_END();
182             }
183              
184             sub is_element {
185 524     524 0 1163 my ($class,$node)=@_;
186 524         3098 return $node->nodeType == XML::LibXML::XML_ELEMENT_NODE();
187             }
188              
189             sub is_attribute {
190 590     590 0 1101 my ($class,$node)=@_;
191 590         2429 return $node->nodeType == XML::LibXML::XML_ATTRIBUTE_NODE();
192             }
193              
194             sub is_text {
195 93     93 0 217 my ($class,$node)=@_;
196 93         580 return $node->nodeType == XML::LibXML::XML_TEXT_NODE();
197             }
198              
199             sub is_text_or_cdata {
200 0     0 0 0 my ($class,$node)=@_;
201 0   0     0 return $node->nodeType == XML::LibXML::XML_TEXT_NODE() || $node->nodeType == XML::LibXML::XML_CDATA_SECTION_NODE();
202             }
203              
204             sub is_cdata_section {
205 54     54 0 118 my ($class,$node)=@_;
206 54         355 return $node->nodeType == XML::LibXML::XML_CDATA_SECTION_NODE();
207             }
208              
209              
210             sub is_pi {
211 49     49 0 116 my ($class,$node)=@_;
212 49         290 return $node->nodeType == XML::LibXML::XML_PI_NODE();
213             }
214              
215             sub is_entity_reference {
216 18     18 0 41 my ($class,$node)=@_;
217 18         87 return $node->nodeType == XML::LibXML::XML_ENTITY_REF_NODE();
218             }
219              
220             sub is_document {
221 710     710 0 1219 my ($class,$node)=@_;
222 710   66     4516 return $node->nodeType == XML::LibXML::XML_DOCUMENT_NODE() ||
223             $node->nodeType == XML::LibXML::XML_HTML_DOCUMENT_NODE();
224             }
225              
226             sub is_document_fragment {
227 72     72 0 200 my ($class,$node)=@_;
228 72         266 return $node->nodeType == XML::LibXML::XML_DOCUMENT_FRAG_NODE();
229             }
230              
231             sub is_comment {
232 60     60 0 136 my ($class,$node)=@_;
233 60         311 return $node->nodeType == XML::LibXML::XML_COMMENT_NODE();
234             }
235              
236             sub is_namespace {
237 34     34 0 95 my ($class,$node)=@_;
238 34         459 return $node->nodeType == XML::LibXML::XML_NAMESPACE_DECL();
239             }
240              
241             sub document_type {
242 2     2 0 7 my ($class,$node)=@_;
243 2         6 my $doc=$class->owner_document($node);
244 2 50       11 if ($doc->nodeType == XML::LibXML::XML_DOCUMENT_NODE) {
    0          
245 2         25 return 'xml';
246             } elsif ($doc->nodeType == XML::LibXML::XML_HTML_DOCUMENT_NODE) {
247 0         0 return 'html';
248             } else {
249 0         0 return 'unknown';
250             }
251             }
252              
253             sub has_dtd {
254 0     0 0 0 my ($class,$doc)=@_;
255 0         0 foreach my $node ($doc->childNodes()) {
256 0 0       0 if ($node->nodeType == XML::LibXML::XML_DTD_NODE()) {
257 0         0 return 1;
258             }
259             }
260 0         0 return 0;
261             }
262              
263             sub get_dtd {
264 1     1 0 17 my ($class,$doc,$quiet)=@_;
265 1         15 my $dtd;
266 1         22 foreach my $node ($doc->childNodes()) {
267 2 100       110 if ($node->nodeType == XML::LibXML::XML_DTD_NODE()) {
268 1 50       33 if ($node->hasChildNodes()) {
269 1         8 $dtd=$node;
270             } else {
271 0         0 my $str=$node->toString();
272 0         0 my $name=$node->getName();
273 0         0 my $public_id;
274             my $system_id;
275 0 0       0 if ($str=~/PUBLIC\s+(\S)([^\1]*\1)\s+(\S)([^\3]*)\3/) {
276 0         0 $public_id=$2;
277 0         0 $system_id=$4;
278             }
279 0 0       0 if ($str=~/SYSTEM\s+(\S)([^\1]*)\1/) {
280 0         0 $system_id=$2;
281             }
282 0 0       0 if ($system_id!~m(/)) {
283 0 0       0 $system_id="$1$system_id" if ($class->doc_URI($doc)=~m(^(.*/)[^/]+$));
284             }
285 0 0       0 print STDERR "loading external dtd: $system_id\n" unless $quiet;
286 0 0       0 $dtd=XML::LibXML::Dtd->new($public_id, $system_id)
287             if $system_id ne "";
288 0 0       0 if ($dtd) {
289 0         0 $dtd->setName($name);
290             } else {
291 0 0       0 print STDERR "failed to load dtd: $system_id\n" unless $quiet;
292             }
293             }
294             }
295             }
296 1         24 return $dtd;
297             }
298              
299             sub clone_node {
300 72     72 0 150 my ($class, $dom, $node)=@_;
301 72         638 return $dom->importNode($node);
302             }
303              
304             sub remove_node {
305 39     39 0 85 my ($class,$node)=@_;
306 39         263 return $node->unbindNode();
307             }
308              
309             sub iterator {
310 0     0 0 0 my ($class,$node)=@_;
311 0         0 my $iter= XML::LibXML::SubTreeIterator->new( $node );
312 0         0 $iter->iterator_function(\&XML::LibXML::SubTreeIterator::subtree_iterator);
313 0         0 return $iter;
314             }
315              
316              
317             package # hide from PAUSE
318             XML::LibXML::SubTreeIterator;
319 8     8   98 use strict;
  8         32  
  8         272  
320 8     8   52 use base qw(XML::LibXML::Iterator);
  8         25  
  8         4169  
321             # (inheritance is not a real necessity here)
322              
323             sub subtree_iterator {
324 0     0   0 my $self = shift;
325 0         0 my $dir = shift;
326 0         0 my $node = undef;
327              
328              
329 0 0       0 if ( $dir < 0 ) {
330             return undef if $self->{CURRENT}->isSameNode( $self->{FIRST} )
331 0 0 0     0 and $self->{INDEX} <= 0;
332              
333 0         0 $node = $self->{CURRENT}->previousSibling;
334 0 0       0 return $self->{CURRENT}->parentNode unless defined $node;
335              
336 0         0 while ( $node->hasChildNodes ) {
337             return undef if $node->isSameNode( $self->{FIRST} )
338 0 0 0     0 and $self->{INDEX} > 0;
339 0         0 $node = $node->lastChild;
340             }
341             }
342             else {
343             return undef if $self->{CURRENT}->isSameNode( $self->{FIRST} )
344 0 0 0     0 and $self->{INDEX} > 0;
345              
346 0 0       0 if ( $self->{CURRENT}->hasChildNodes ) {
347 0         0 $node = $self->{CURRENT}->firstChild;
348             }
349             else {
350 0         0 $node = $self->{CURRENT}->nextSibling;
351 0         0 my $pnode = $self->{CURRENT}->parentNode;
352 0         0 while ( not defined $node ) {
353 0 0       0 last unless defined $pnode;
354 0 0       0 return undef if $pnode->isSameNode( $self->{FIRST} );
355 0         0 $node = $pnode->nextSibling;
356 0 0       0 $pnode = $pnode->parentNode unless defined $node;
357             }
358             }
359             }
360              
361 0         0 return $node;
362             }
363              
364             {
365             local $^W=0;
366 8 0 0 8 0 76 eval <<'EOF';
  8 0 0 8 1 20  
  8 0 0 8 0 79  
  8 0 0 0 0 5772  
  8 0 0 2   20  
  8 0 0 160   212  
  0 0 0 0   0  
  0 0 0 0   0  
  0 0 0 9   0  
  0 0       0  
  0 50       0  
  0 50       0  
  0 50       0  
  0 0       0  
  0 0       0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  8         4256  
  8         19  
  8         200  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  2         10  
  2         7  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  2         21  
  2         70  
  0         0  
  160         8290  
  160         333  
  160         1533  
  0         0  
  160         1095  
  160         803  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  9         42  
  9         39  
  11         57  
  11         168  
  9         44  
367             package # hide from PAUSE
368             XML::LibXML::Namespace;
369             sub parentNode {}
370              
371             package # hide from PAUSE
372             XML::LibXML::NodeList;
373              
374             use overload
375             '""' => \&value,
376             '0+' => \&value,
377             '+' => \&add,
378             '-' => \&subtract,
379             'bool' => \&to_boolean,
380             'fallback' => undef;
381              
382             sub add {
383             if (UNIVERSAL::isa($_[1],'XML::LibXML::NodeList')) {
384             if (defined($_[2])) {
385             $_[2] ? XML::LibXML::NodeList->new(@{$_[1]},@{$_[0]}) :
386             XML::LibXML::NodeList->new(@{$_[0]},@{$_[1]});
387             } else {
388             $_[0]->append($_[1]);
389             $_[0]
390             }
391             } else {
392             $_[0]->value + $_[1]
393             }
394             }
395              
396             sub subtract {
397             if (UNIVERSAL::isa($_[1],'XML::LibXML::NodeList')) {
398             my ($plus,$minus);
399             ($plus,$minus)= $_[2] ? ($_[1],$_[0]) : ($_[0],$_[1]);
400             my %minus; @minus{ map $$_,@$minus } = ();
401             return XML::LibXML::NodeList->new(grep !exists($minus{$$_}),@$plus);
402             } else {
403             $_[0]->value - $_[1]
404             }
405             }
406              
407             sub value {
408             my $self = CORE::shift;
409             my $result = join('', grep {defined $_} map { $_->string_value } @$self);
410             return $result;
411             }
412              
413             package # hide from PAUSE
414             XML::LibXML::Literal;
415             use overload
416             '""' => \&value,
417             '0+' => \&value,
418             'cmp' => \&cmp,
419             '<=>' => sub { defined($_[2]) && $_[2] ? ($_[1] <=> ${$_[0]}) : (${$_[0]} <=> $_[1]) },
420             '+' => sub { ${$_[0]}+$_[1] },
421             '-' => sub { defined($_[2]) && $_[2] ? $_[1]-${$_[0]} : ${$_[0]}-$_[1] },
422             '*' => sub { ${$_[0]}*$_[1] },
423             '**' => sub { ${$_[0]}**$_[1] },
424             '/' => sub { ${$_[0]}/$_[1] },
425             '%' => sub { ${$_[0]}%$_[1] },
426             'x' => sub { defined($_[2]) && $_[2] ? $_[1] x ${$_[0]} : ${$_[0]} x $_[1] },
427             'fallback' => undef;
428              
429              
430             package # hide form PAUSE
431             XML::LibXML::Number;
432              
433             use overload
434             '""' => \&value,
435             '0+' => \&value,
436             '<=>' => \&cmp,
437             'cmp' => sub { defined($_[2]) && $_[2] ? ($_[1] cmp ${$_[0]}) : (${$_[0]} cmp $_[1]) },
438             '+' => sub { ${$_[0]}+$_[1] },
439             '-' => sub { defined($_[2]) && $_[2] ? $_[1]-${$_[0]} : ${$_[0]}-$_[1] },
440             '*' => sub { ${$_[0]}*$_[1] },
441             '**' => sub { defined($_[2]) && $_[2] ? $_[1]**${$_[0]} : ${$_[0]}**$_[1] },
442             '/' => sub { defined($_[2]) && $_[2] ? $_[1]/${$_[0]} : ${$_[0]}/$_[1] },
443             '%' => sub { defined($_[2]) && $_[2] ? $_[1] % ${$_[0]} : ${$_[0]} % $_[1] },
444             'x' => sub { defined($_[2]) && $_[2] ? $_[1] x ${$_[0]} : ${$_[0]} x $_[1] },
445             'fallback' => undef;
446              
447             sub new {
448             my $class = shift;
449             my $number = shift;
450             if ($number !~ /^\s*(-\s*)?(\d+(\.\d*)?|\.\d+)\s*$/) {
451             $number = undef;
452             }
453             else {
454             $number =~ s/\s*//g;
455             }
456             bless \$number, $class;
457             }
458              
459             EOF
460             die $@ if $@;
461             };
462              
463              
464              
465             1;
466              
467