File Coverage

blib/lib/Padre/Task/SyntaxChecker/XML.pm
Criterion Covered Total %
statement 9 9 100.0
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 12 12 100.0


line stmt bran cond sub pod time code
1             package Padre::Task::SyntaxChecker::XML;
2 1     1   1273 use strict;
  1         2  
  1         37  
3 1     1   5 use warnings;
  1         2  
  1         45  
4              
5             our $VERSION = '0.10';
6              
7 1     1   5 use base 'Padre::Task::Syntax';
  1         2  
  1         847  
8             use XML::LibXML;
9              
10             =pod
11              
12             =head1 NAME
13              
14             Padre::Task::SyntaxChecker::XML - XML document syntax-checking in the background
15              
16             =head1 SYNOPSIS
17              
18             # by default, the text of the current document
19             # will be fetched as will the document's notebook page.
20             my $task = Padre::Task::SyntaxChecker::XML->new();
21             $task->schedule;
22              
23             my $task2 = Padre::Task::SyntaxChecker::XML->new(
24             text => Padre::Documents->current->text_get,
25             filename => Padre::Documents->current->editor->{Document}->filename,
26             on_finish => sub { my $task = shift; ... },
27             );
28             $task2->schedule;
29              
30             =head1 DESCRIPTION
31              
32             This class implements syntax checking of XML documents in
33             the background. It inherits from L.
34             Please read its documentation!
35              
36             =cut
37              
38             =for cmt
39             sub run {
40             my $self = shift;
41             $self->_check_syntax();
42             return 1;
43             }
44             =cut
45              
46             sub _valid {
47             my $base_uri = shift;
48             my $text = shift;
49              
50             my $validator = XML::LibXML->new();
51             $validator->validation(0);
52             $validator->line_numbers(1);
53             $validator->base_uri($base_uri);
54             $validator->load_ext_dtd(1);
55             $validator->expand_entities(1);
56              
57             my $doc = '';
58             eval {
59             $doc = $validator->parse_string($text , $base_uri );
60             };
61              
62             if ($@) {
63             # parser error
64             return _parse_msg( $@, $base_uri );
65             }
66             else {
67             if ( $doc->internalSubset() ) {
68             $validator->validation(1);
69             eval {
70             $doc = $validator->parse_string( $text, $base_uri );
71             };
72             if ($@) {
73             # validation error
74             return _parse_msg( $@, $base_uri );
75             }
76             else {
77             return [];
78             }
79             }
80             else {
81             return [];
82             }
83             }
84              
85             }
86              
87             sub _check_syntax {
88             my $self = shift;
89              
90             my $base_uri = $self->{filename};
91              
92             $self->{syntax_check} = _valid ($base_uri, $self->{text});
93              
94             return;
95             }
96              
97             sub _parse_msg {
98             my ( $error, $base_uri ) = @_;
99              
100             $error =~ s/${base_uri}:/:/g;
101             $error =~ s/\sat\s.+?LibXML.pm\sline.+//go;
102              
103             my @messages = split( /\n:/, $error );
104              
105             my $issues = [];
106              
107             my $m = shift @messages;
108              
109             if ( $m =~ m/^:(\d+):\s+(.+)/o ) {
110             push @{$issues}, { msg => $2, line => $1, severity => 'E', desc => '' };
111             }
112             else {
113             push @{$issues}, { msg => $m, line => $error, severity => 'E', desc => '' };
114             }
115              
116             foreach my $m (@messages) {
117             $m =~ m/^(\d+):\s+(.+)/o;
118             push @{$issues}, { msg => $2, line => $1, severity => 'E', desc => '' };
119             }
120              
121             return $issues;
122             }
123              
124             sub syntax {
125             my $self = shift;
126             my $text = shift;
127             if (not $self->{filename}) {
128             print "error - no filename\n";
129             }
130             my $base_uri = $self->{filename};
131              
132             return _valid($base_uri, $text);
133             }
134             1;
135              
136             __END__