File Coverage

blib/lib/XML/Liberal/LibXML.pm
Criterion Covered Total %
statement 60 60 100.0
branch 11 16 68.7
condition 6 9 66.6
subroutine 14 14 100.0
pod 2 5 40.0
total 93 104 89.4


line stmt bran cond sub pod time code
1             package XML::Liberal::LibXML;
2 4     4   22 use strict;
  4         5  
  4         91  
3              
4 4     4   15 use Carp;
  4         5  
  4         166  
5 4     4   749 use XML::LibXML;
  4         27526  
  4         19  
6 4     4   1732 use XML::Liberal::Error;
  4         6  
  4         17  
7              
8 4     4   109 use base qw( XML::Liberal );
  4         6  
  4         235  
9              
10             our $XML_LibXML_new;
11              
12             sub globally_override {
13 25     25 1 35 my $class = shift;
14              
15 4     4   107 no warnings 'redefine';
  4         6  
  4         435  
16 25 50       59 unless ($XML_LibXML_new) {
17 25         42 $XML_LibXML_new = \&XML::LibXML::new;
18 25     72   100 *XML::LibXML::new = sub { XML::Liberal->new('LibXML') };
  72         19913  
19             }
20              
21 25         41 1;
22             }
23              
24             sub globally_unoverride {
25 24     24 0 37 my $class = shift;
26              
27 4     4   20 no warnings 'redefine';
  4         6  
  4         1048  
28 24 50       51 if ($XML_LibXML_new) {
29 24         103 *XML::LibXML::new = $XML_LibXML_new;
30 24         36 undef $XML_LibXML_new;
31             }
32              
33 24         73 return 1;
34             }
35              
36             sub new {
37 170     170 1 244 my $class = shift;
38 170         319 my %param = @_;
39              
40 170         415 my $self = bless { %param }, $class;
41 170 100       674 $self->{parser} = $XML_LibXML_new
42             ? $XML_LibXML_new->('XML::LibXML') : XML::LibXML->new;
43              
44 170         2078 $self;
45             }
46              
47             sub extract_error {
48 195     195 0 277 my $self = shift;
49 195         374 my($exn, $xml_ref) = @_;
50              
51             # for XML::LibXML > 1.69. Some time between lixml2 2.9.4 and 2.9.12,
52             # multiple errors are returned as an array you need to unwind using
53             # _prev. Stringifying the root error still gives the combined errors,
54             # joined by newlines.
55 195 50       439 if (ref $exn eq 'XML::LibXML::Error') {
56 195         380 $exn = $exn->as_string;
57             }
58 195         39232 my @errors = split /\n/, $exn;
59              
60             # strip internal error and unregistered error message
61 195   66     1128 while ($errors[0] =~ /^:\d+: parser error : internal error/ ||
62             $errors[0] =~ /^:\d+: parser error : Unregistered error message/) {
63 28         140 splice @errors, 0, 3;
64             }
65              
66 195 100       1120 my $line = $errors[0] =~ s/^:(\d+):\s*// ? $1 : undef;
67              
68 195         340 my ($column, $location);
69 195 50 66     743 if (defined $line && defined $errors[1] && defined $errors[2]) {
      66        
70 190         225 my $line_start = 0;
71             $line_start = 1 + index $$xml_ref, "\n", $line_start
72 190         968 for 2 .. $line;
73 4     4   22 no warnings 'utf8'; # if fixing bad UTF-8, such warnings are confusing
  4         6  
  4         579  
74 190 100       793 if (my ($spaces) = $errors[2] =~ /^(\s*)\^/) {
75 180         341 my $context = substr $errors[1], 0, length $spaces;
76 180         409 pos($$xml_ref) = $line_start;
77 180 50       3135 if ($$xml_ref =~ /\G.*?\Q$context\E /x) {
78 180         512 $location = $+[0];
79 180         310 $column = $location - $line_start + 1;
80             }
81 180         358 pos($$xml_ref) = undef; # so future matches work as expected
82             }
83             }
84              
85 195         1357 return XML::Liberal::Error->new({
86             message => $errors[0],
87             line => $line,
88             column => $column,
89             location => $location,
90             });
91             }
92              
93             # recover() is not useful for Liberal parser ... IMHO
94       24 0   sub recover { }
95              
96             1;