655
|
1 |
#
|
|
2 |
# Use XML::DOM::ValParser instead of XML::DOM::Parser and it will
|
|
3 |
# use XML::Checker to validate XML at parse time.
|
|
4 |
#
|
|
5 |
|
|
6 |
package XML::DOM::ValParser;
|
|
7 |
|
|
8 |
use strict;
|
|
9 |
use XML::DOM;
|
|
10 |
use XML::Checker::Parser;
|
|
11 |
|
|
12 |
use vars qw( @ISA @SupportedHandlers );
|
|
13 |
|
|
14 |
@ISA = qw( XML::Checker::Parser );
|
|
15 |
|
|
16 |
# These XML::Parser handlers are currently supported by XML::DOM
|
|
17 |
@SupportedHandlers = qw( Init Final Char Start End Default Doctype
|
|
18 |
CdataStart CdataEnd XMLDecl Entity Notation Proc
|
|
19 |
Default Comment Attlist Element Unparsed );
|
|
20 |
|
|
21 |
sub new
|
|
22 |
{
|
|
23 |
my ($class, %args) = @_;
|
|
24 |
|
|
25 |
my %handlers = ();
|
|
26 |
for (@SupportedHandlers)
|
|
27 |
{
|
|
28 |
my $domHandler = "XML::Parser::Dom::$_";
|
|
29 |
$handlers{$_} = \&$domHandler;
|
|
30 |
}
|
|
31 |
$args{Handlers} = \%handlers;
|
|
32 |
$class->SUPER::new (%args);
|
|
33 |
}
|
|
34 |
|
|
35 |
sub parse
|
|
36 |
{
|
|
37 |
# Do what XML::DOM::Parser normally does.
|
|
38 |
# Temporarily override his @ISA, so that he thinks he's a
|
|
39 |
# XML::DOM::ValParser and calls the right SUPER::parse(),
|
|
40 |
# (otherwise he thinks he's an XML::DOM::Parser and you see runtime
|
|
41 |
# error: Can't call method "Init" on unblessed reference ...)
|
|
42 |
local @XML::DOM::Parser::ISA = @ISA;
|
|
43 |
local $XML::Checker::Parser::_skipInsignifWS = $_[0]->{SkipInsignifWS};
|
|
44 |
XML::DOM::Parser::parse (@_);
|
|
45 |
}
|
|
46 |
|
|
47 |
1; # package return code
|
|
48 |
|
|
49 |
__END__
|
|
50 |
|
|
51 |
=head1 NAME
|
|
52 |
|
|
53 |
XML::DOM::ValParser - an XML::DOM::Parser that validates at parse time
|
|
54 |
|
|
55 |
=head1 SYNOPSIS
|
|
56 |
|
|
57 |
use XML::DOM::ValParser;
|
|
58 |
|
|
59 |
my %expat_options = (KeepCDATA => 1,
|
|
60 |
Handlers => [ Unparsed => \&my_Unparsed_handler ]);
|
|
61 |
my $parser = new XML::DOM::ValParser (%expat_options);
|
|
62 |
|
|
63 |
eval {
|
|
64 |
local $XML::Checker::FAIL = \&my_fail;
|
|
65 |
my $doc = $parser->parsefile ("fail.xml");
|
|
66 |
... XML::DOM::Document was created sucessfully ...
|
|
67 |
};
|
|
68 |
if ($@) {
|
|
69 |
# Either XML::Parser (expat) threw an exception or my_fail() died.
|
|
70 |
... your error handling code here ...
|
|
71 |
# Note that the XML::DOM::Document is automatically disposed off and
|
|
72 |
# will be garbage collected
|
|
73 |
}
|
|
74 |
|
|
75 |
# Throws an exception (with die) when an error is encountered, this
|
|
76 |
# will stop the parsing process.
|
|
77 |
# Don't die if a warning or info message is encountered, just print a message.
|
|
78 |
sub my_fail {
|
|
79 |
my $code = shift;
|
|
80 |
die XML::Checker::error_string ($code, @_) if $code < 200;
|
|
81 |
XML::Checker::print_error ($code, @_);
|
|
82 |
}
|
|
83 |
|
|
84 |
=head1 DESCRIPTION
|
|
85 |
|
|
86 |
Use XML::DOM::ValParser wherever you would use L<XML::DOM::Parser> and
|
|
87 |
your XML will be checked using L<XML::Checker> at parse time.
|
|
88 |
|
|
89 |
See L<XML::DOM> for details on XML::DOM::Parser options.
|
|
90 |
See L<XML::Checker> for details on setting the fail handler (my_fail.)
|
|
91 |
|
|
92 |
The following handlers are currently supported, just like XML::DOM::Parser:
|
|
93 |
Init, Final, Char, Start, End, Default, Doctype, CdataStart, CdataEnd,
|
|
94 |
XMLDecl, Entity, Notation, Proc, Default, Comment, Attlist, Element, Unparsed.
|
|
95 |
|
|
96 |
=head1 XML::DOM::ValParser
|
|
97 |
|
|
98 |
XML::DOM::ValParser extends from L<XML::Checker::Parser>. It creates an
|
|
99 |
L<XML::Checker> object and routes all event handlers through the checker,
|
|
100 |
before processing the events to create the XML::DOM::Document.
|
|
101 |
|
|
102 |
Just like L<XML::Checker::Parser>, the checker object can be retrieved with
|
|
103 |
the getChecker() method and can be reused later on (provided that the DOCTYPE
|
|
104 |
section of the XML::DOM::Document did not change in the mean time.)
|
|
105 |
|
|
106 |
You can control which errors are fatal (and therefore should stop creation
|
|
107 |
of the XML::DOM::Document) by filtering the appropriate error codes in
|
|
108 |
the global $XML::Checker::FAIL handler
|
|
109 |
(see L<XML::Checker/ERROR_HANDLING>) and
|
|
110 |
calling I<die> or I<croak> appropriately.
|
|
111 |
|
|
112 |
Just like XML::Checker::Parser, XML::DOM::ValParser supports the
|
|
113 |
SkipExternalDTD and SkipInsignifWS options. See L<XML::Checker::Parser>
|
|
114 |
for details.
|
|
115 |
|
|
116 |
=head1 AUTHOR
|
|
117 |
|
|
118 |
Send bug reports, hints, tips, suggestions to Enno Derksen at
|
|
119 |
<F<enno@att.com>>.
|
|
120 |
|
|
121 |
=head1 SEE ALSO
|
|
122 |
|
|
123 |
L<XML::DOM>, L<XML::Checker> (L<XML::Checker/SEE_ALSO>)
|