File Coverage

blib/lib/XML/Liberal/LibXML.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package XML::Liberal::LibXML;
2 1     1   7 use strict;
  1         3  
  1         50  
3              
4 1     1   6 use Carp;
  1         2  
  1         87  
5 1     1   548 use XML::LibXML;
  0            
  0            
6             use XML::Liberal::Error;
7              
8             use base qw( XML::Liberal );
9              
10             our $XML_LibXML_new;
11              
12             sub globally_override {
13             my $class = shift;
14              
15             no warnings 'redefine';
16             unless ($XML_LibXML_new) {
17             $XML_LibXML_new = \&XML::LibXML::new;
18             *XML::LibXML::new = sub { XML::Liberal->new('LibXML') };
19             }
20              
21             1;
22             }
23              
24             sub globally_unoverride {
25             my $class = shift;
26              
27             no warnings 'redefine';
28             if ($XML_LibXML_new) {
29             *XML::LibXML::new = $XML_LibXML_new;
30             undef $XML_LibXML_new;
31             }
32              
33             return 1;
34             }
35              
36             sub new {
37             my $class = shift;
38             my %param = @_;
39              
40             my $self = bless { %param }, $class;
41             $self->{parser} = $XML_LibXML_new
42             ? $XML_LibXML_new->('XML::LibXML') : XML::LibXML->new;
43              
44             $self;
45             }
46              
47             sub extract_error {
48             my $self = shift;
49             my($exn, $xml_ref) = @_;
50              
51             # for XML::LibXML > 1.69
52             if (ref $exn eq 'XML::LibXML::Error') {
53             while($exn->_prev) {
54             last if $exn->message =~/Unregistered error message/;
55             last if $exn->message =~/internal error/;
56             $exn = $exn->_prev
57             }
58             $exn = $exn->as_string;
59             }
60             my @errors = split /\n/, $exn;
61              
62             # strip internal error and unregistered error message
63             while ($errors[0] =~ /^:\d+: parser error : internal error/ ||
64             $errors[0] =~ /^:\d+: parser error : Unregistered error message/) {
65             splice @errors, 0, 3;
66             }
67              
68             my $line = $errors[0] =~ s/^:(\d+):\s*// ? $1 : undef;
69              
70             my ($column, $location);
71             if (defined $line && defined $errors[1] && defined $errors[2]) {
72             my $line_start = 0;
73             $line_start = 1 + index $$xml_ref, "\n", $line_start
74             for 2 .. $line;
75             no warnings 'utf8'; # if fixing bad UTF-8, such warnings are confusing
76             if (my ($spaces) = $errors[2] =~ /^(\s*)\^/) {
77             my $context = substr $errors[1], 0, length $spaces;
78             pos($$xml_ref) = $line_start;
79             if ($$xml_ref =~ /\G.*?\Q$context\E /x) {
80             $location = $+[0];
81             $column = $location - $line_start + 1;
82             }
83             pos($$xml_ref) = undef; # so future matches work as expected
84             }
85             }
86              
87             return XML::Liberal::Error->new({
88             message => $errors[0],
89             line => $line,
90             column => $column,
91             location => $location,
92             });
93             }
94              
95             # recover() is not useful for Liberal parser ... IMHO
96             sub recover { }
97              
98             1;