File Coverage

blib/lib/XML/Liberal.pm
Criterion Covered Total %
statement 22 65 33.8
branch 1 22 4.5
condition 1 4 25.0
subroutine 7 17 41.1
pod 2 6 33.3
total 33 114 28.9


line stmt bran cond sub pod time code
1             package XML::Liberal;
2              
3 2     2   635 use strict;
  2         4  
  2         62  
4 2     2   54 use 5.008_001;
  2         8  
  2         97  
5             our $VERSION = '0.30';
6              
7 2     2   10 use base qw( Class::Accessor );
  2         3  
  2         1143  
8 2     2   2285 use Carp;
  2         4  
  2         164  
9 2     2   1546 use UNIVERSAL::require;
  2         3229  
  2         18  
10             use Module::Pluggable::Fast
11 2         816 name => 'remedies',
12             search => [ 'XML::Liberal::Remedy' ],
13 2     2   1946 require => 1;
  2         5996  
14              
15             __PACKAGE__->remedies(); # load remedies now
16             __PACKAGE__->mk_accessors(qw( max_fallback guess_encodings ));
17              
18             our $Debug;
19              
20             sub debug {
21 0     0 0 0 my $self = shift;
22 0 0       0 $self->{debug} = shift if @_;
23 0 0       0 $self->{debug} || $XML::Liberal::Debug;
24             }
25              
26             sub new {
27 1     1 1 13 my $class = shift;
28 1   50     4 my $driver = shift || 'LibXML';
29              
30 1         4 my $subclass = "XML::Liberal::$driver";
31 1 50       11 $subclass->require or die $@;
32              
33 0           my %param = @_;
34 0 0         $param{max_fallback} = 15 unless defined $param{max_fallback};
35              
36 0           $subclass->new(%param);
37             }
38              
39             sub globally_override {
40 0     0 1   my $class = shift;
41 0   0       my $driver = shift || 'LibXML';
42              
43 0           my $subclass = "XML::Liberal::$driver";
44 0 0         $subclass->require or die $@;
45              
46 0           $subclass->globally_override;
47              
48 0 0         if (defined wantarray) {
49             return XML::Liberal::Destructor->new(
50 0     0     sub { $subclass->globally_unoverride },
51 0           );
52             }
53              
54 0           return;
55             }
56              
57             sub parse_string {
58 0     0 0   my $self = shift;
59 0           my($xml) = @_;
60              
61             TRY:
62 0           for (1 .. $self->max_fallback) {
63 0           my $doc = eval { $self->{parser}->parse_string($xml) };
  0            
64 0 0         return $doc if $doc;
65              
66 0           my $error = $self->extract_error($@, \$xml);
67 0           for my $remedy (sort $self->remedies) {
68 0 0         warn "considering $remedy\n" if $self->debug;
69 0 0         $remedy->apply($self, $error, \$xml) or next;
70 0 0         warn "--- remedy applied: $xml\n" if $self->debug;
71 0           next TRY;
72             }
73              
74             # We've considered all possible remedies for this error, and none
75             # worked, so just throw an exception.
76 0           Carp::croak($error->summary);
77             }
78             }
79              
80             sub parse_file {
81 0     0 0   my($self, $file) = @_;
82 0 0         open my $fh, "<", $file or croak "$file: $!";
83 0           $self->parse_fh($fh);
84             }
85              
86             sub parse_fh {
87 0     0 0   my($self, $fh) = @_;
88 0           my $xml = join '', <$fh>;
89 0           $self->parse_string($xml);
90             }
91              
92             our $AUTOLOAD;
93             sub AUTOLOAD {
94 0     0     my($self, @args) = @_;
95 0           (my $meth = $AUTOLOAD) =~ s/.*:://;
96 0           $self->{parser}->$meth(@args);
97             }
98              
99             sub DESTROY {
100 0     0     my $self = shift;
101 0           delete $self->{parser};
102             }
103              
104             package XML::Liberal::Destructor;
105              
106             sub new {
107 0     0     my($class, $callback) = @_;
108 0           bless { cb => $callback }, $class;
109             }
110              
111             sub DESTROY {
112 0     0     my $self = shift;
113 0           $self->{cb}->();
114             }
115              
116             package XML::Liberal;
117              
118             1;
119             __END__