XML-Checker-0.13/0040775000076500007650000000000007537726371013716 5ustar tjmathertjmatherXML-Checker-0.13/lib/0040775000076500007650000000000007444142142014445 5ustar tjmathertjmatherXML-Checker-0.13/lib/XML/0040775000076500007650000000000007511712240015102 5ustar tjmathertjmatherXML-Checker-0.13/lib/XML/Checker/0040775000076500007650000000000007537725376016474 5ustar tjmathertjmatherXML-Checker-0.13/lib/XML/Checker/Parser.pm0100644000076500007650000004032707507777564020272 0ustar tjmathertjmatherpackage XML::Checker::Parser; use strict; use XML::Parser; use XML::Checker; use vars qw( @ISA @InterceptedHandlers @SGML_SEARCH_PATH %URI_MAP $_checker $_prevFAIL $_Init $_Final $_Char $_Start $_End $_Element $_Attlist $_Doctype $_Unparsed $_Notation $_Entity $_skipInsignifWS $_EndOfDoc ); @ISA = qw( XML::Parser ); @InterceptedHandlers = qw( Init Final Char Start End Element Attlist Doctype Unparsed Notation Entity ); # Where to search for external DTDs (in local file system) @SGML_SEARCH_PATH = (); # Where to search for external DTDs as referred to by public ID in a # statement, e.g. "-//W3C//DTD HTML 4.0//EN" # E.g. it could map "-//W3C//DTD HTML 4.0//EN" to "file:/user/html.dtd" %URI_MAP = (); sub new { my ($class, %args) = @_; my $super = new XML::Parser (%args); $super->{Checker} = new XML::Checker (%args); my %handlers = %{$super->{Handlers}}; # Don't need Comment handler - assuming comments are allowed anywhere #?? What should Default handler do? #?? Check XMLDecl, ExternEnt, Proc? No, for now. #?? Add CdataStart, CdataEnd support? for (@InterceptedHandlers) { my $func = "XML::Checker::Parser::$_"; $handlers{$_} = \&$func; } $super->{UserHandlers} = $super->{Handlers}; $super->{Handlers} = \%handlers; bless $super, $class; } sub getChecker { $_[0]->{Checker} } sub parse { my $self = shift; my $uh = $self->{UserHandlers}; local $_checker = $self->{Checker}; local $_Init = $uh->{Init}; local $_Final = $uh->{Final}; local $_Start = $uh->{Start}; local $_End = $uh->{End}; local $_Char = $uh->{Char}; local $_Element = $uh->{'Element'}; local $_Attlist = $uh->{'Attlist'}; local $_Doctype = $uh->{Doctype}; local $_Unparsed = $uh->{Unparsed}; local $_Notation = $uh->{Notation}; local $_Entity = $uh->{Entity}; local $_prevFAIL = $XML::Checker::FAIL; local $XML::Checker::FAIL = \&fail_add_context; local $XML::Checker::INSIGNIF_WS = 0; local $_skipInsignifWS = $self->{SkipInsignifWS}; local $_EndOfDoc = 0; $self->SUPER::parse (@_); } my $LWP_USER_AGENT; sub set_LWP_UserAgent # static { $LWP_USER_AGENT = shift; } sub load_URL # static { my ($url, $lwp_user_agent) = @_; my $result; # Read the file from the web with LWP. # # Note that we read in the entire file, which may not be ideal # for large files. LWP::UserAgent also provides a callback style # request, which we could convert to a stream with a fork()... my $response; eval { use LWP::UserAgent; my $ua = $lwp_user_agent; unless (defined $ua) { unless (defined $LWP_USER_AGENT) { $LWP_USER_AGENT = LWP::UserAgent->new; # Load proxy settings from environment variables, i.e.: # http_proxy, ftp_proxy, no_proxy etc. (see LWP::UserAgent(3)) # You need these to go thru firewalls. $LWP_USER_AGENT->env_proxy; } $ua = $LWP_USER_AGENT; } my $req = new HTTP::Request 'GET', $url; $response = $LWP_USER_AGENT->request ($req); $result = $response->content; }; if ($@) { die "Couldn't load URL [$url] with LWP: $@"; } if (!$result) { my $message = $response->as_string; die "Couldn't load URL [$url] with LWP: $message"; } return $result; } sub parsefile { my $self = shift; my $url = shift; # Any other URL schemes? if ($url =~ /^(https?|ftp|wais|gopher|file):/) { my $xml = load_URL ($url, $self->{LWP_UserAgent}); my $result; eval { # Parse the result of the HTTP request $result = $self->parse ($xml, @_); }; if ($@) { die "Couldn't parsefile [$url]: $@"; } return $result; } else { return $self->SUPER::parsefile ($url, @_); } } sub Init { my $expat = shift; $_checker->{Expat} = $expat; $_checker->Init (@_); &$_Init ($expat) if $_Init; } sub Final { my $expat = shift; $_EndOfDoc = 1; $_checker->Final (@_); my $result = &$_Final ($expat) if $_Final; # Decouple Expat from Checker delete $_checker->{Expat}; # NOTE: Checker is not decoupled return $result; } sub Start { my ($expat, $tag, @attr) = @_; $_checker->Start ($tag); my $num_spec = $expat->specified_attr; for (my $i = 0; $i < @attr; $i++) { my $spec = ($i < $num_spec); my $attr = $attr[$i]; my $val = $attr[++$i]; # print "--- $tag $attr $val $spec\n"; $_checker->Attr ($tag, $attr, $val, $spec); } $_checker->EndAttr; &$_Start ($expat, $tag, @attr) if $_Start; } sub End { my $expat = shift; $_checker->End (@_); &$_End ($expat, @_) if $_End; } sub Char { my $expat = shift; $_checker->Char (@_); &$_Char ($expat, @_) if $_Char && !($XML::Checker::INSIGNIF_WS && $_skipInsignifWS); # Skip insignificant whitespace } sub Element { my $expat = shift; $_checker->Element (@_); &$_Element ($expat, @_) if $_Element; } sub Attlist { my $expat = shift; $_checker->Attlist (@_); &$_Attlist ($expat, @_) if $_Attlist; } sub Doctype { my $expat = shift; my ($name, $sysid, $pubid, $internal) = @_; my $dtd; unless ($_checker->{SkipExternalDTD}) { if ($sysid) { # External DTD... #?? I'm not sure if we should die here or keep going? $dtd = load_DTD ($sysid, $expat->{LWP_UserAgent}); } elsif ($pubid) { $dtd = load_DTD ($pubid, $expat->{LWP_UserAgent}); } } if (defined $dtd) { #?? what about passing ProtocolEncoding, Namespaces, Stream_Delimiter ? my $parser = new XML::Parser ( Checker => $_checker, ErrorContext => $expat->{ErrorContext}, Handlers => { Entity => \&XML::Checker::Parser::ExternalDTD::Entity, Notation => \&XML::Checker::Parser::ExternalDTD::Notation, Element => \&XML::Checker::Parser::ExternalDTD::Element, Attlist => \&XML::Checker::Parser::ExternalDTD::Attlist, Unparsed => \&XML::Checker::Parser::ExternalDTD::Unparsed, }); eval { $parser->parse ("\n<$name/>"); }; if ($@) { die "Couldn't parse contents of external DTD <$sysid> :$@"; } } $_checker->Doctype (@_); &$_Doctype ($expat, @_) if $_Doctype; } sub Unparsed { my $expat = shift; $_checker->Unparsed (@_); &$_Unparsed ($expat, @_) if $_Unparsed; } sub Entity { my $expat = shift; $_checker->Entity (@_); &$_Entity ($expat, @_) if $_Entity; } sub Notation { my $expat = shift; $_checker->Notation (@_); &$_Notation ($expat, @_) if $_Notation; } sub Default { #?? what can I check here? # print "Default handler got[" . join (", ", @_) . "]"; } #sub XMLDecl #{ #?? support later? #} sub setHandlers { my ($self, %h) = @_; my (%oldhandlers); for my $name (@InterceptedHandlers) { if (exists $h{$name}) { $oldhandlers{$name} = $self->{UserHandlers}->{$name}; $self->{UserHandlers}->{$name} = $h{$name}; delete $h{$name}; } } # Pass remaining handlers to the parent class (XML::Parser) return (%oldhandlers, $self->SUPER::setHandlers (%h)); } # Add (line, column, byte) to error context (unless it's EOF) sub fail_add_context # static { my $e = $_checker->{Expat}; my $byte = $e->current_byte; # -1 means: end of XML document if ($byte != -1 && !$_EndOfDoc) { push @_, (line => $e->current_line, column => $e->current_column, byte => $byte); } &$_prevFAIL (@_); } #-------- STATIC METHODS related to External DTDs --------------------------- sub load_DTD # static { my ($sysid, $lwp_user_agent) = @_; # See if it is defined in the %URI_MAP # (Public IDs are stored here, e.g. "-//W3C//DTD HTML 4.0//EN") if (exists $URI_MAP{$sysid}) { $sysid = $URI_MAP{$sysid}; } elsif ($sysid !~ /^\w+:/) { # Prefix the sysid with 'file:' if it has no protocol identifier unless ($sysid =~ /^\//) { # Not an absolute path. See if it's in SGML_SEARCH_PATH. my $relative_sysid = $sysid; $sysid = find_in_sgml_search_path ($sysid); if (! $sysid) { if ($ENV{'SGML_SEARCH_PATH'}) { die "Couldn't find external DTD [$relative_sysid] in SGML_SEARCH_PATH ($ENV{'SGML_SEARCH_PATH'})"; } else { die "Couldn't find external DTD [$relative_sysid], may be you should set SGML_SEARCH_PATH"; } } } $sysid = "file:$sysid"; } return load_URL ($sysid, $lwp_user_agent); } sub map_uri # static { %URI_MAP = (%URI_MAP, @_); } sub set_sgml_search_path # static { @SGML_SEARCH_PATH = @_; } sub find_in_sgml_search_path # static { my $file = shift; my @dirs = @SGML_SEARCH_PATH; unless (@dirs) { my $path = $ENV{SGML_SEARCH_PATH}; if ($path) { @dirs = split (':', $path); } else { my $home = $ENV{HOME}; @dirs = (".", "$home/.sgml", "/usr/lib/sgml", "/usr/share/sgml"); } } for my $directory (@dirs) { if (-e "$directory/$file") { return "$directory/$file"; } } return undef; } package XML::Checker::Parser::ExternalDTD; sub Element { my $expat = shift; $expat->{Checker}->Element(@_); } sub Attlist { my $expat = shift; $expat->{Checker}->Attlist(@_); } sub Unparsed { my $expat = shift; $expat->{Checker}->Unparsed(@_); } sub Notation { my $expat = shift; $expat->{Checker}->Notation(@_); } sub Entity { my $expat = shift; # print "Entity: $expat\n"; $expat->{Checker}->Entity(@_); } sub my_final { return 1; } 1; # package return code __END__ =head1 NAME XML::Checker::Parser - an XML::Parser that validates at parse time =head1 SYNOPSIS use XML::Checker::Parser; my %expat_options = (KeepCDATA => 1, Handlers => [ Unparsed => \&my_Unparsed_handler ]); my $parser = new XML::Checker::Parser (%expat_options); eval { local $XML::Checker::FAIL = \&my_fail; $parser->parsefile ("fail.xml"); }; if ($@) { # Either XML::Parser (expat) threw an exception or my_fail() died. ... your error handling code here ... } # Throws an exception (with die) when an error is encountered, this # will stop the parsing process. # Don't die if a warning or info message is encountered, just print a message. sub my_fail { my $code = shift; die XML::Checker::error_string ($code, @_) if $code < 200; XML::Checker::print_error ($code, @_); } =head1 DESCRIPTION XML::Checker::Parser extends L I hope the example in the SYNOPSIS says it all, just use L as if it were an XML::Parser. See L for the supported (expat) options. You can also derive your parser from XML::Checker::Parser instead of from XML::Parser. All you should have to do is replace: package MyParser; @ISA = qw( XML::Parser ); with: package MyParser; @ISA = qw( XML::Checker::Parser ); =head1 XML::Checker::Parser constructor $parser = new XML::Checker::Parser (SkipExternalDTD => 1, SkipInsignifWS => 1); The constructor takes the same parameters as L with the following additions: =over 4 =item SkipExternalDTD By default, it will try to load external DTDs using LWP. You can disable this by setting SkipExternalDTD to 1. See L for details. =item SkipInsignifWS By default, it will treat insignificant whitespace as regular Char data. By setting SkipInsignifWS to 1, the user Char handler will not be called if insignificant whitespace is encountered. See L for details. =item LWP_UserAgent When calling parsefile() with a URL (instead of a filename) or when loading external DTDs, we use LWP to download the remote file. By default it will use a L that is created as follows: use LWP::UserAgent; $LWP_USER_AGENT = LWP::UserAgent->new; $LWP_USER_AGENT->env_proxy; Note that L reads proxy settings from your environment variables, which is what I need to do to get thru our firewall. If you want to use a different LWP::UserAgent, you can either set it globally with: XML::Checker::Parser::set_LWP_UserAgent ($my_agent); or, you can specify it for a specific XML::Checker::Parser by passing it to the constructor: my $parser = new XML::Checker::Parser (LWP_UserAgent => $my_agent); Currently, LWP is used when the filename (passed to parsefile) starts with one of the following URL schemes: http, https, ftp, wais, gopher, or file (followed by a colon.) If I missed one, please let me know. The LWP modules are part of libwww-perl which is available at CPAN. =back =head1 External DTDs XML::Checker::Parser will try to load and parse external DTDs that are referenced in DOCTYPE definitions unless you set the B option to 1 (the default setting is 0.) See L for details on what is not supported by XML::Checker::Parser. L (version 2.27 and up) does a much better job at reading external DTDs, because recently external DTD parsing was added to expat. Make sure you set the L option B to 1 and the XML::Checker::Parser option B to 1. (They can both be set in the XML::Checker::Parser constructor.) When external DTDs are parsed by XML::Checker::Parser, they are located in the following order: =over 4 =item * With the %URI_MAP, which can be set using B. This hash maps external resource ids (like system ID's and public ID's) to full path URI's. It was meant to aid in resolving PUBLIC IDs found in DOCTYPE declarations after the PUBLIC keyword, e.g. However, you can also use this to force L to read DTDs from a different URL than was specified (e.g. from the local file system for performance reasons.) =item * on the Internet, if their system identifier starts with a protocol (like http://...) =item * on the local disk, if their system identifier starts with a slash (absolute path) =item * in the SGML_SEARCH_PATH, if their system identifier is a relative file name. It will use @SGML_SEARCH_PATH if it was set with B, or the colon-separated $ENV{SGML_SEARCH_PATH}, or (if that isn't set) the list (".", "$ENV{'HOME'}/.sgml", "/usr/lib/sgml", "/usr/share/sgml"), which includes the current directory, so it should do the right thing in most cases. =back =head2 Static methods related to External DTDs =over 4 =item set_sgml_search_path (dir1, dir2, ...) External DTDs with relative file paths are looked up using the @SGML_SEARCH_PATH, which can be set with this method. If @SGML_SEARCH_PATH is never set, it will use the colon-separated $ENV{SGML_SEARCH_PATH} instead. If neither are set it uses the list: ".", "$ENV{'HOME'}/.sgml", "/usr/lib/sgml", "/usr/share/sgml". set_sgml_search_path is a static method. =item map_uri (pubid => uri, ...) To define the location of PUBLIC ids, as found in DOCTYPE declarations after the PUBLIC keyword, e.g. call this method, e.g. XML::Checker::Parser::map_uri ( "-//W3C//DTD HTML 4.0//EN" => "file:/user/html.dtd"); See L for more info. XML::Checker::Parser::map_uri is a static method. =back =head1 Switching user handlers at parse time You should be able to use setHandlers() just as in L. (Using setHandlers has not been tested yet.) =head1 Error handling XML::Checker::Parser routes the fail handler through XML::Checker::Parser::fail_add_context() before calling your fail handler (i.e. the global fail handler: $XML::Checker::FAIL. See L.) It adds the (line, column, byte) information from L to the error context (unless it was the end of the XML document.) =head1 Supported XML::Parser handlers Only the following L handlers are currently routed through L: Init, Final, Char, Start, End, Element, Attlist, Doctype, Unparsed, Notation. =head1 CAVEATS When using XML::Checker::Parser to parse external DTDs (i.e. with SkipExternalDTD => 0), expect trouble when your external DTD contains parameter entities inside declarations or conditional sections. The external DTD should probably have the same encoding as the orignal XML document. =head1 AUTHOR Enno Derksen is the original author. Send bug reports, hints, tips, suggestions to T.J. Mather at >. =head1 SEE ALSO L (L), L XML-Checker-0.13/lib/XML/Checker/DOM.pm0100644000076500007650000000015007045411144017413 0ustar tjmathertjmatherBEGIN { warn "XML::Checker::DOM has been deprecated. The methods have been merged into XML::DOM." } XML-Checker-0.13/lib/XML/DOM/0040775000076500007650000000000007444142142015524 5ustar tjmathertjmatherXML-Checker-0.13/lib/XML/DOM/ValParser.pm0100644000076500007650000000747707342255000017766 0ustar tjmathertjmather# # Use XML::DOM::ValParser instead of XML::DOM::Parser and it will # use XML::Checker to validate XML at parse time. # package XML::DOM::ValParser; use strict; use XML::DOM; use XML::Checker::Parser; use vars qw( @ISA @SupportedHandlers ); @ISA = qw( XML::Checker::Parser ); # These XML::Parser handlers are currently supported by XML::DOM @SupportedHandlers = qw( Init Final Char Start End Default Doctype CdataStart CdataEnd XMLDecl Entity Notation Proc Default Comment Attlist Element Unparsed ); sub new { my ($class, %args) = @_; my %handlers = (); for (@SupportedHandlers) { my $domHandler = "XML::Parser::Dom::$_"; $handlers{$_} = \&$domHandler; } $args{Handlers} = \%handlers; $class->SUPER::new (%args); } sub parse { # Do what XML::DOM::Parser normally does. # Temporarily override his @ISA, so that he thinks he's a # XML::DOM::ValParser and calls the right SUPER::parse(), # (otherwise he thinks he's an XML::DOM::Parser and you see runtime # error: Can't call method "Init" on unblessed reference ...) local @XML::DOM::Parser::ISA = @ISA; local $XML::Checker::Parser::_skipInsignifWS = $_[0]->{SkipInsignifWS}; XML::DOM::Parser::parse (@_); } 1; # package return code __END__ =head1 NAME XML::DOM::ValParser - an XML::DOM::Parser that validates at parse time =head1 SYNOPSIS use XML::DOM::ValParser; my %expat_options = (KeepCDATA => 1, Handlers => [ Unparsed => \&my_Unparsed_handler ]); my $parser = new XML::DOM::ValParser (%expat_options); eval { local $XML::Checker::FAIL = \&my_fail; my $doc = $parser->parsefile ("fail.xml"); ... XML::DOM::Document was created sucessfully ... }; if ($@) { # Either XML::Parser (expat) threw an exception or my_fail() died. ... your error handling code here ... # Note that the XML::DOM::Document is automatically disposed off and # will be garbage collected } # Throws an exception (with die) when an error is encountered, this # will stop the parsing process. # Don't die if a warning or info message is encountered, just print a message. sub my_fail { my $code = shift; die XML::Checker::error_string ($code, @_) if $code < 200; XML::Checker::print_error ($code, @_); } =head1 DESCRIPTION Use XML::DOM::ValParser wherever you would use L and your XML will be checked using L at parse time. See L for details on XML::DOM::Parser options. See L for details on setting the fail handler (my_fail.) The following handlers are currently supported, just like XML::DOM::Parser: Init, Final, Char, Start, End, Default, Doctype, CdataStart, CdataEnd, XMLDecl, Entity, Notation, Proc, Default, Comment, Attlist, Element, Unparsed. =head1 XML::DOM::ValParser XML::DOM::ValParser extends from L. It creates an L object and routes all event handlers through the checker, before processing the events to create the XML::DOM::Document. Just like L, the checker object can be retrieved with the getChecker() method and can be reused later on (provided that the DOCTYPE section of the XML::DOM::Document did not change in the mean time.) You can control which errors are fatal (and therefore should stop creation of the XML::DOM::Document) by filtering the appropriate error codes in the global $XML::Checker::FAIL handler (see L) and calling I or I appropriately. Just like XML::Checker::Parser, XML::DOM::ValParser supports the SkipExternalDTD and SkipInsignifWS options. See L for details. =head1 AUTHOR Enno Derksen is the original author. Send bug reports, hints, tips, suggestions to T.J. Mather at >. =head1 SEE ALSO L, L (L) XML-Checker-0.13/lib/XML/Checker.pm0100644000076500007650000013570007511712416017012 0ustar tjmathertjmatheruse warnings; use strict; # # # TO DO # - update docs regarding PerlSAX interface # - add current node to error context when checking DOM subtrees # - add parsed Entity to test XML files # - free circular references # - Implied handler? # - Notation, Entity, Unparsed checks, Default handler? # - check no root element (it's checked by expat) ? package XML::Checker::Term; use strict; sub new { my ($class, %h) = @_; bless \%h, $class; } sub str { '<' . $_[0]->{C} . $_[0]->{N} . '>' } sub re { $_[0]->{S} } sub rel { my $self = shift; defined $self->{SL} ? @{ $self->{SL} } : ( $self->{S} ); } sub debug { my $t = shift; my ($c, $n, $s) = ($t->{C}, $t->{N}, $t->{S}); my @sl = $t->rel; "{C=$c N=$n S=$s SL=@sl}"; } #------------------------------------------------------------------------- package XML::Checker::Context; sub new { my ($class) = @_; my $scalar; bless \$scalar, $class; } sub Start {} sub End {} sub Char {} # # The initial Context when checking an entire XML Document # package XML::Checker::DocContext; use vars qw( @ISA ); @ISA = qw( XML::Checker::Context ); sub new { #??checker not used my ($class, $checker) = @_; bless { }, $class; } sub setRootElement { $_[0]->{RootElement} = $_[1]; } sub Start { my ($self, $checker, $tag) = @_; if (exists $self->{Elem}) { my $tags = join (", ", @{$self->{Elem}}); $checker->fail (155, "more than one root Element [$tags]"); push @{$self->{Elem}}, $tag; } else { $self->{Elem} = [ $tag ]; } my $exp_root = $self->{RootElement}; $checker->fail (156, "unexpected root Element [$tag], expected [$exp_root]") if defined ($exp_root) and $tag ne $exp_root; } sub debug { my $self = shift; "DocContext[Count=" . $self->{Count} . ",Root=" . $self->{RootElement} . "]"; } package XML::Checker::Context::ANY; use vars qw( @ISA ); @ISA = qw( XML::Checker::Context ); # No overrides, because everything is accepted sub debug { "XML::Checker::Context::ANY" } package XML::Checker::Context::EMPTY; use vars qw( @ISA $ALLOW_WHITE_SPACE ); @ISA = qw( XML::Checker::Context ); $ALLOW_WHITE_SPACE = 0; sub debug { "XML::Checker::Context::EMPTY" } sub Start { my ($self, $checker, $tag) = @_; $checker->fail (152, "Element should be EMPTY, found Element [$tag]"); } sub Char { my ($self, $checker, $str) = @_; $checker->fail (153, "Element should be EMPTY, found text [$str]") unless ($ALLOW_WHITE_SPACE and $checker->isWS ($str)); # NOTE: if $ALLOW_WHITE_SPACE = 1, the isWS call does not only check # whether it is whitespace, but it also informs the checker that this # might be insignificant whitespace } #?? what about Comments package XML::Checker::Context::Children; use vars qw( @ISA ); @ISA = qw( XML::Checker::Context ); sub new { my ($class, $rule) = @_; bless { Name => $rule->{Name}, RE => $rule->{RE}, Buf => "", N => 0 }, $class; } sub phash { my $href = shift; my $str = ""; for (keys %$href) { $str .= ' ' if $str; $str .= $_ . '=' . $href->{$_}; } $str; } sub debug { my $self = shift; "Context::Children[Name=(" . phash ($self->{Name}) . ",N=" . $self->{N} . ",RE=" . $self->{RE} . ",Buf=[" . $self->{Buf} . "]"; } sub Start { my ($self, $checker, $tag) = @_; #print "Children.Start tag=$tag rule=$checker drule=" . $checker->debug . "\n"; if (exists $self->{Name}->{$tag}) { #print "Buf=[".$self->{Buf}. "] tag=[" . $self->{Name}->{$tag}->{S} . "]\n"; $self->{Buf} .= $self->{Name}->{$tag}->{S}; } else { $checker->fail (157, "unexpected Element [$tag]", ChildElementIndex => $self->{N}) } $self->{N}++; } sub decode { my ($self) = @_; my $re = $self->{RE}; my $name = $self->{Name}; my $buf = $self->{Buf}; # length of token, in a content model all tokens are the same length my $len = 0; my %s = (); while (my ($key, $val) = each %$name) { $len = length($val->{S}) unless $len; $s{$val->{S}} = $key; } # ex. $key = C_31 and $name = 01 #use warnings; my $dots = "[^()*+?|]" x $len; $buf =~ s/($dots)/$s{$1} . ","/ge; chop $buf; $re =~ s/($dots)/"(" . $s{$1} . ")"/ge; "Found=[$buf] RE=[$re]" } sub End { my ($self, $checker) = @_; my $re = $self->{RE}; unless ( $self->{Buf} =~ /\S/ ) { unless ( $self->{Buf} =~ /^$re$/ ) { $checker->fail (170, "Element can't be empty " . $self->decode); return; } } unless ( $self->{Buf} =~ /^$re$/ ) { $checker->fail (154, "bad order of Elements " . $self->decode); } } sub Char { my ($self, $checker, $str) = @_; $checker->fail (149, "Element should only contain sub elements, found text [$str]") unless ($checker->isWS ($str)); } package XML::Checker::Context::Mixed; use vars qw( @ISA ); @ISA = qw( XML::Checker::Context ); sub new { my ($class, $rule) = @_; bless { Name => $rule->{Name}, N => 0 }, $class; } sub debug { my $self = shift; "Context::Mixed[Name=" . $self->{Name} . ",N=" , $self->{N} . "]"; } sub Start { my ($self, $checker, $tag) = @_; $checker->fail (157, "unexpected Element [$tag]", ChildElementIndex => $self->{N}) unless exists $self->{Name}->{$tag}; $self->{N}++; } package XML::Checker::ERule; package XML::Checker::ERule::EMPTY; use vars qw( @ISA ); @ISA = qw( XML::Checker::ERule ); sub new { my ($class) = @_; bless {}, $class; } my $context = new XML::Checker::Context::EMPTY; sub context { $context } # share the context sub debug { "EMPTY" } package XML::Checker::ERule::ANY; use vars qw( @ISA ); @ISA = qw( XML::Checker::ERule ); sub new { my ($class) = @_; bless {}, $class; } my $any_context = new XML::Checker::Context::ANY; sub context { $any_context } # share the context sub debug { "ANY" } package XML::Checker::ERule::Mixed; use vars qw( @ISA ); @ISA = qw( XML::Checker::ERule ); sub new { my ($class) = @_; bless { Name => {} }, $class; } sub context { my ($self) = @_; new XML::Checker::Context::Mixed ($self); } sub setModel { my ($self, $model) = @_; my $rule = $model; # Mixed := '(' '#PCDATA' ')' '*'? if ($rule =~ /^\(\s*#PCDATA\s*\)(\*)?$/) { #? how do we interpret the '*' ?? return 1; } else # Mixed := '(' '#PCDATA' ('|' Name)* ')*' { return 0 unless $rule =~ s/^\(\s*#PCDATA\s*//; return 0 unless $rule =~ s/\s*\)\*$//; my %names = (); while ($rule =~ s/^\s*\|\s*($XML::RegExp::Name)//) { $names{$1} = 1; } if ($rule eq "") { $self->{Name} = \%names; return 1; } } return 0; } sub debug { my ($self) = @_; "Mixed[Names=" . join("|", keys %{$self->{Name}}) . "]"; } package XML::Checker::ERule::Children; use vars qw( @ISA %_name %_map $_n ); @ISA = qw( XML::Checker::ERule ); sub new { my ($class) = @_; bless {}, $class; } sub context { my ($self) = @_; new XML::Checker::Context::Children ($self); } sub _add # static { my $exp = new XML::Checker::Term (@_); $_map{$exp->{N}} = $exp; $exp->str; } my $IDS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; sub _tokenize { my ($self, $rule) = @_; # Replace names with Terms of the form "", e.g. "". # Lookup already used names and store new names in %_name. # $$rule =~ s/($XML::RegExp::Name)(?!>)/ if (exists $_name{$1}) # name already used? { $_name{$1}->str; } else { my $exp = new XML::Checker::Term (C => 'n', N => $_n++, Name => $1); $_name{$1} = $_map{$exp->{N}} = $exp; $exp->str; } /eg; if ($_n < length $IDS) { # Generate regular expression for the name Term, i.e. # a single character from $IDS my $i = 0; for (values %_name) { $_->{S} = substr ($IDS, $i++, 1); #print "tokenized " . $_->{Name} . " num=" . $_->{N} . " to " . $_->{S} . "\n"; } } else { # Generate RE, convert Term->{N} to hex string # e.g. "03d". Calculate needed length of hex string first. my $len = 0; for (my $n = $_n - 1; $n > 0; $len++) { $n = $n >> 4; } my $i = 0; for (values %_name) { $_->{S} = sprintf ("%0${len}lx", $i++); #print "tokenized " . $_->{Name} . " num=" . $_->{N} . " to " . $_->{S} . "\n"; } } } sub setModel { my ($self, $rule) = @_; local $_n = 0; local %_map = (); local %_name = (); $self->_tokenize (\$rule); #?? check for single name - die "!ELEMENT contents can't be just a NAME" if $rule =~ /^$XML::RegExp::Name$/; for ($rule) { my $n = 1; while ($n) { $n = 0; # cp := ( name | choice | seq ) ('?' | '*' | '+')? $n++ while s/<[ncs](\d+)>([?*+]?)/_add (C => 'a', N => $_n++, S => ($_map{$1}->re . $2))/eg; # choice := '(' ch_l ')' $n++ while s/\(\s*<[ad](\d+)>\s*\)/_add (C => 'c', N => $_n++, S => "(" . join ("|", $_map{$1}->rel) . ")")/eg; # ch_l := ( cp | ch_l ) '|' ( cp | ch_l ) $n++ while s/<[ad](\d+)>\s*\|\s*<[ad](\d+)>/_add (C => 'd', N => $_n++, SL => [ $_map{$1}->rel, $_map{$2}->rel ])/eg; # seq := '(' (seq_l ')' $n++ while s/\(\s*<[at](\d+)>\s*\)/_add (C => 's', N => $_n++, S => "(".join("", $_map{$1}->rel).")")/eg; # seq_l := ( cp | seq_l ) ',' ( cp | seq_l ) $n++ while s/<[at](\d+)>\s*,\s*<[at](\d+)>/_add (C => 't', N => $_n++, SL => [ $_map{$1}->rel, $_map{$2}->rel ])/eg; } } return 0 if ($rule !~ /^$/); $self->{Name} = \%_name; $self->{RE} = $_map{$1}->re; return 1; } sub debug { my ($self) = @_; "Children[RE=" . $self->{RE} . "]"; } package XML::Checker::ARule; use XML::RegExp; sub new { my ($class, $elem, $checker) = @_; bless { Elem => $elem, Checker => $checker, Required => {} }, $class; } sub Attlist { my ($self, $attr, $type, $default, $fixed, $checker) = @_; my ($c1, $c2); if ($self->{Defined}->{$attr}) { my $tag = $self->{Elem}; $self->fail ($attr, 110, "attribute [$attr] of element [$tag] already defined"); } else { $self->{Defined}->{$attr} = 1; } if ($default =~ /^\#(REQUIRED|IMPLIED)$/) { $c1 = $1; # Keep list of all required attributes if ($default eq '#REQUIRED') { $self->{Required}->{$attr} = 1; } } else { $self->fail ($attr, 122, "invalid default attribute value [$default]") unless $default =~ /^$XML::RegExp::AttValue$/; $default = substr ($default, 1, length($default)-2); $self->{Default}->{$attr} = $default; $c1 = 'FIXED' if $fixed; } if ($type eq 'ID') { $self->fail ($attr, 123, "invalid default ID [$default], must be #REQUIRED or #IMPLIED") unless $default =~ /^#(REQUIRED|IMPLIED)$/; if (exists ($self->{ID}) && $self->{ID} ne $attr) { $self->fail ($attr, 151, "only one ID allowed per ELEMENT " . "first=[" . $self->{ID} . "]"); } else { $self->{ID} = $attr; } $c2 = 'ID'; } elsif ($type =~ /^(IDREF|IDREFS|ENTITY|ENTITIES|NMTOKEN|NMTOKENS)$/) { my $def = $self->{Default}->{$attr}; if (defined $def) { my $re = ($type =~ /^[IE]/) ? $XML::RegExp::Name : $XML::RegExp::NmToken; if ($type =~ /S$/) { for (split (/\s+/, $def)) { $self->fail ($attr, 121, "invalid default [$_] in $type [$def]") unless $_ =~ /^$re$/; } } else # singular { $self->fail ($attr, 120, "invalid default $type [$def]") unless $def =~ /^$re$/; } } $c2 = $type; } elsif ($type ne 'CDATA') # Enumerated := NotationType | Enumeration { if ($type =~ /^\s*NOTATION\s*\(\s*($XML::RegExp::Name(\s*\|\s*$XML::RegExp::Name)*)\s*\)\s*$/) { $self->fail ($attr, 135, "empty NOTATION list in ATTLIST") unless defined $1; my @tok = split (/\s*\|\s*/, $1); for (@tok) { $self->fail ($attr, 100, "undefined NOTATION [$_] in ATTLIST") unless exists $checker->{NOTATION}->{$_}; } my $re = join ("|", @tok); $self->{NotationRE} = "^($re)\$"; $c2 = 'NotationType'; } elsif ($type =~ /^\s*\(\s*($XML::RegExp::NmToken(\s*\|\s*$XML::RegExp::NmToken)*)\s*\)\s*$/) { # Enumeration $self->fail ($attr, 136, "empty Enumeration list in ATTLIST") unless defined $1; my @tok = split (/\s*\|\s*/, $1); for (@tok) { $self->fail ($attr, 134, "invalid Enumeration value [$_] in ATTLIST") unless $_ =~ /^$XML::RegExp::NmToken$/; } $self->{EnumRE}->{$attr} = '^(' . join ("|", @tok) . ')$'; #'; $c2 = 'Enumeration'; } else { $self->fail ($attr, 137, "invalid ATTLIST type [$type]"); } } $self->{Check1}->{$attr} = $c1 if $c1; $self->{Check2}->{$attr} = $c2 if $c2; } sub fail { my $self = shift; my $attr = shift; $self->{Checker}->fail (@_, Element => $self->{Elem}, Attr => $attr); } sub check { my ($self, $attr) = @_; my $func1 = $self->{Check1}->{$attr}; my $func2 = $self->{Check2}->{$attr}; # print "check func1=$func1 func2=$func2 @_\n"; if (exists $self->{ReqNotSeen}->{$attr}) { delete $self->{ReqNotSeen}->{$attr}; } no strict; &$func1 (@_) if defined $func1; &$func2 (@_) if defined $func2; } # Copies the list of all required attributes from $self->{Required} to # $self->{ReqNotSeen}. # When check() encounters a required attribute, it is removed from ReqNotSeen. # In EndAttr we look at which attribute names are still in ReqNotSeen - those # are the ones that were not specified and are, therefore, in error. sub StartAttr { my $self = shift; my %not_seen = %{ $self->{Required} }; $self->{ReqNotSeen} = \%not_seen; } # Checks which of the #REQUIRED attributes were not specified sub EndAttr { my $self = shift; for my $attr (keys %{ $self->{ReqNotSeen} }) { $self->fail ($attr, 159, "unspecified value for \#REQUIRED attribute [$attr]"); } } sub FIXED { my ($self, $attr, $val, $specified) = @_; my $default = $self->{Default}->{$attr}; $self->fail ($attr, 150, "bad \#FIXED attribute value [$val], it should be [$default]") unless ($val eq $default); } sub IMPLIED { my ($self, $attr, $val, $specified) = @_; #?? should #IMPLIED be specified? $self->fail ($attr, 158, "unspecified value for \#IMPLIED attribute [$attr]") unless $specified; #?? Implied handler ? } # This is called when an attribute is passed to the check() method by # XML::Checker::Attr(), i.e. when the attribute was specified explicitly # or defaulted by the parser (which should never happen), *NOT* when the # attribute was omitted. (The latter is checked by StartAttr/EndAttr) sub REQUIRED { my ($self, $attr, $val, $specified) = @_; # print "REQUIRED attr=$attr val=$val spec=$specified\n"; $self->fail ($attr, 159, "unspecified value for \#REQUIRED attribute [$attr]") unless $specified; } sub ID # must be #IMPLIED or #REQUIRED { my ($self, $attr, $val, $specified) = @_; $self->fail ($attr, 131, "invalid ID [$val]") unless $val =~ /^$XML::RegExp::Name$/; $self->fail ($attr, 111, "ID [$val] already defined") if $self->{Checker}->{ID}->{$val}++; } sub IDREF { my ($self, $attr, $val, $specified) = @_; $self->fail ($attr, 132, "invalid IDREF [$val]") unless $val =~ /^$XML::RegExp::Name$/; $self->{Checker}->{IDREF}->{$val}++; } sub IDREFS { my ($self, $attr, $val, $specified) = @_; for (split /\s+/, $val) { $self->IDREF ($attr, $_); } } sub ENTITY { my ($self, $attr, $val, $specified) = @_; #?? should it be specified? $self->fail ($attr, 133, "invalid ENTITY name [$val]") unless $val =~ /^$XML::RegExp::Name$/; $self->fail ($attr, 102, "undefined unparsed ENTITY [$val]") unless exists $self->{Checker}->{Unparsed}->{$val}; } sub ENTITIES { my ($self, $attr, $val, $specified) = @_; for (split /\s+/, $val) { $self->ENTITY ($attr, $_); } } sub NMTOKEN { my ($self, $attr, $val, $specified) = @_; $self->fail ($attr, 130, "invalid NMTOKEN [$val]") unless $val =~ /^$XML::RegExp::NmToken$/; } sub NMTOKENS { my ($self, $attr, $val, $specified) = @_; for (split /\s+/, $val) { $self->NMTOKEN ($attr, $_, $specified); } } sub Enumeration { my ($self, $attr, $val, $specified) = @_; my $re = $self->{EnumRE}->{$attr}; $self->fail ($attr, 160, "invalid Enumeration value [$val]") unless $val =~ /$re/; } sub NotationType { my ($self, $attr, $val, $specified) = @_; my $re = $self->{NotationRE}; $self->fail ($attr, 161, "invalid NOTATION value [$val]") unless $val =~ /$re/; $self->fail ($attr, 162, "undefined NOTATION [$val]") unless exists $self->{Checker}->{NOTATION}->{$val}; } package XML::Checker; use vars qw ( $VERSION $FAIL $INSIGNIF_WS ); BEGIN { $VERSION = '0.13'; } $FAIL = \&print_error; # Whether the last seen Char data was insignicant whitespace $INSIGNIF_WS = 0; sub new { my ($class, %args) = @_; $args{ERule} = {}; $args{ARule} = {}; $args{InCDATA} = 0; #$args{Debug} = 1; bless \%args, $class; } # PerlSAX API sub element_decl { my ($self, $hash) = @_; $self->Element ($hash->{Name}, $hash->{Model}); } # Same parameter order as the Element handler in XML::Parser module sub Element { my ($self, $name, $model) = @_; if (defined $self->{ERule}->{$name}) { $self->fail (115, "ELEMENT [$name] already defined", Element => $name); } if ($model eq "EMPTY") { $self->{ERule}->{$name} = new XML::Checker::ERule::EMPTY; } elsif ($model eq "ANY") { $self->{ERule}->{$name} = new XML::Checker::ERule::ANY; } elsif ($model =~ /#PCDATA/) { my $rule = new XML::Checker::ERule::Mixed; if ($rule->setModel ($model)) { $self->{ERule}->{$name} = $rule; } else { $self->fail (124, "bad model [$model] for ELEMENT [$name]", Element => $name); } } else { my $rule = new XML::Checker::ERule::Children; if ($rule->setModel ($model)) { $self->{ERule}->{$name} = $rule; } else { $self->fail (124, "bad model [$model] for ELEMENT [$name]", Element => $name); } } my $rule = $self->{ERule}->{$name}; print "added ELEMENT model for $name: " . $rule->debug . "\n" if $rule and $self->{Debug}; } # PerlSAX API sub attlist_decl { my ($self, $hash) = @_; $self->Attlist ($hash->{ElementName}, $hash->{AttributeName}, $hash->{Type}, $hash->{Default}, $hash->{Fixed}); } sub Attlist { my ($self, $tag, $attrName, $type, $default, $fixed) = @_; my $arule = $self->{ARule}->{$tag} ||= new XML::Checker::ARule ($tag, $self); $arule->Attlist ($attrName, $type, $default, $fixed, $self); } # Initializes the context stack to check an XML::DOM::Element sub InitDomElem { my $self = shift; # initialize Context stack $self->{Context} = [ new XML::Checker::Context::ANY ($self) ]; $self->{InCDATA} = 0; } # Clears the context stack after checking an XML::DOM::Element sub FinalDomElem { my $self = shift; delete $self->{Context}; } # PerlSAX API sub start_document { shift->Init; } sub Init { my $self = shift; # initialize Context stack $self->{Context} = [ new XML::Checker::DocContext ($self) ]; $self->{InCDATA} = 0; } # PerlSAX API sub end_document { shift->Final; } sub Final { my $self = shift; #?? could add more statistics: unreferenced Unparsed, ID for (keys %{ $self->{IDREF} }) { my $n = $self->{IDREF}->{$_}; $self->fail (200, "undefined ID [$_] was referenced [$n] times") unless defined $self->{ID}->{$_}; } for (keys %{ $self->{ID} }) { my $n = $self->{IDREF}->{$_} || 0; $self->fail (300, "[$n] references to ID [$_]"); } delete $self->{Context}; } sub getRootElement { my $self = shift; # print "getRoot $self " . $self->{RootElement} . "\n"; $_[0]->{RootElement}; } # PerlSAX API sub doctype_decl { my ($self, $hash) = @_; $self->Doctype ($hash->{Name}, $hash->{SystemId}, $hash->{PublicId}, $hash->{Internal}); } sub Doctype { my ($self, $name, $sysid, $pubid, $internal) = @_; $self->{RootElement} = $name; my $context = $self->{Context}->[0]; $context->setRootElement ($name); #?? what else } sub Attr { my ($self, $tag, $attr, $val, $specified) = @_; #print "Attr for tag=$tag attr=$attr val=$val spec=$specified\n"; my $arule = $self->{ARule}->{$tag}; if (defined $arule && $arule->{Defined}->{$attr}) { $arule->check ($attr, $val, $specified); } else { $self->fail (103, "undefined attribute [$attr]", Element => $tag); } } sub EndAttr { my $self = shift; my $arule = $self->{CurrARule}; if (defined $arule) { $arule->EndAttr; } } # PerlSAX API sub start_element { my ($self, $hash) = @_; my $tag = $hash->{Name}; my $attr = $hash->{Attributes}; $self->Start ($tag); if (exists $hash->{AttributeOrder}) { my $defaulted = $hash->{Defaulted}; my @order = @{ $hash->{AttributeOrder} }; # Specified attributes for (my $i = 0; $i < $defaulted; $i++) { my $a = $order[$i]; $self->Attr ($tag, $a, $attr->{$a}, 1); } # Defaulted attributes for (my $i = $defaulted; $i < @order; $i++) { my $attr = $order[$i]; $self->Attr ($tag, $a, $attr->{$a}, 0); } } else { # Assume all attributes were specified my @attr = %$attr; my ($key, $val); while ($key = shift @attr) { $val = shift @attr; $self->Attr ($tag, $key, $val, 1); } } $self->EndAttr; } sub Start { my ($self, $tag) = @_; #?? if first tag, check with root element - or does expat check this already? my $context = $self->{Context}; $context->[0]->Start ($self, $tag); my $erule = $self->{ERule}->{$tag}; if (defined $erule) { unshift @$context, $erule->context; } else { # It's not a real error according to the XML Spec. $self->fail (101, "undefined ELEMENT [$tag]"); unshift @$context, new XML::Checker::Context::ANY; } #?? what about ARule ?? my $arule = $self->{ARule}->{$tag}; if (defined $arule) { $self->{CurrARule} = $arule; $arule->StartAttr; } } # PerlSAX API sub end_element { shift->End; } sub End { my ($self) = @_; my $context = $self->{Context}; $context->[0]->End ($self); shift @$context; } # PerlSAX API sub characters { my ($self, $hash) = @_; my $data = $hash->{Data}; if ($self->{InCDATA}) { $self->CData ($data); } else { $self->Char ($data); } } # PerlSAX API sub start_cdata { $_[0]->{InCDATA} = 1; } # PerlSAX API sub end_cdata { $_[0]->{InCDATA} = 0; } sub Char { my ($self, $text) = @_; my $context = $self->{Context}; # NOTE: calls to isWS may set this to 1. $INSIGNIF_WS = 0; $context->[0]->Char ($self, $text); } # Treat CDATASection same as Char (Text) sub CData { my ($self, $cdata) = @_; my $context = $self->{Context}; $context->[0]->Char ($self, $cdata); # CDATASection can never be insignificant whitespace $INSIGNIF_WS = 0; #?? I'm not sure if this assumption is correct } # PerlSAX API sub comment { my ($self, $hash) = @_; $self->Comment ($hash->{Data}); } sub Comment { # ?? what can be checked here? } # PerlSAX API sub entity_reference { my ($self, $hash) = @_; $self->EntityRef ($hash->{Name}, 0); #?? parameter entities (like %par;) are NOT supported! # PerlSAX::handle_default should be fixed! } sub EntityRef { my ($self, $ref, $isParam) = @_; if ($isParam) { # expand to "%name;" print STDERR "XML::Checker::Entity - parameter Entity (%ent;) not implemented\n"; } else { # Treat same as Char - for now my $context = $self->{Context}; $context->[0]->Char ($self, "&$ref;"); $INSIGNIF_WS = 0; #?? I could count the number of times each Entity is referenced } } # PerlSAX API sub unparsed_entity_decl { my ($self, $hash) = @_; $self->Unparsed ($hash->{Name}); #?? what about Base, SytemId, PublicId ? } sub Unparsed { my ($self, $entity) = @_; # print "ARule::Unparsed $entity\n"; if ($self->{Unparsed}->{$entity}) { $self->fail (112, "unparsed ENTITY [$entity] already defined"); } else { $self->{Unparsed}->{$entity} = 1; } } # PerlSAX API sub notation_decl { my ($self, $hash) = @_; $self->Notation ($hash->{Name}); #?? what about Base, SytemId, PublicId ? } sub Notation { my ($self, $notation) = @_; if ($self->{NOTATION}->{$notation}) { $self->fail (113, "NOTATION [$notation] already defined"); } else { $self->{NOTATION}->{$notation} = 1; } } # PerlSAX API sub entity_decl { my ($self, $hash) = @_; $self->Entity ($hash->{Name}, $hash->{Value}, $hash->{SystemId}, $hash->{PublicId}, $hash->{'Notation'}); } sub Entity { my ($self, $name, $val, $sysId, $pubId, $ndata) = @_; if (exists $self->{ENTITY}->{$name}) { $self->fail (114, "ENTITY [$name] already defined"); } else { $self->{ENTITY}->{$name} = $val; } } # PerlSAX API #sub xml_decl {} $hash=> Version, Encoding, Standalone # Don't implement resolve_entity() which is called by ExternEnt! #sub processing_instruction {} $hash=> Target, Data # Returns whether the Char data is whitespace and also updates the # $INSIGNIF_WS variable to indicate whether it is insignificant whitespace. # Note that this method is only called in places where potential whitespace # can be insignificant (i.e. when the ERule is Children or EMPTY) sub isWS { # pverdret: why not /\A\s+\Z/ ??? $INSIGNIF_WS = ($_[1] =~ /^\s*$/); } sub isInsignifWS { $INSIGNIF_WS; } sub fail { my $self = shift; &$FAIL (@_); } sub print_error # static { my $str = error_string (@_); print STDERR $str; } sub error_string # static { my $code = shift; my $msg = shift; my @a = (); my ($key, $val); while ($key = shift) { $val = shift; push @a, ("$key " . (defined $val ? $val : "(undef)")); } my $cat = $code >= 200 ? ($code >= 300 ? "INFO" : "WARNING") : "ERROR"; my $str = join (", ", @a); $str = length($str) ? "\tContext: $str\n" : ""; "XML::Checker $cat-$code: $msg\n$str"; } sub debug { my ($self) = @_; my $context = $self->{Context}->[0]; my $c = $context ? $context->debug : "no context"; my $root = $self->{RootElement}; "Checker[$c,RootElement=$root]"; } 1; # package return code __END__ =head1 NAME XML::Checker - A perl module for validating XML =head1 SYNOPSIS L - an L that validates at parse time L - an L that validates at parse time (Some of the package names may change! This is only an alpha release...) =head1 DESCRIPTION XML::Checker can be used in different ways to validate XML. See the manual pages of L and L for more information. This document only describes common topics like error handling and the XML::Checker class itself. WARNING: Not all errors are currently checked. Almost everything is subject to change. Some reported errors may not be real errors. For production code, it is recommended that you use L or L instead of L. Both modules share the same DTD validation code with libxml2 and L is easier to install. =head1 ERROR HANDLING Whenever XML::Checker (or one of the packages that uses XML::Checker) detects a potential error, the 'fail handler' is called. It is currently also called to report information, like how many times an Entity was referenced. (The whole error handling mechanism is subject to change, I'm afraid...) The default fail handler is XML::Checker::print_error(), which prints an error message to STDERR. It does not stop the XML::Checker, so it will continue looking for other errors. The error message is created with XML::Checker::error_string(). You can define your own fail handler in two ways, locally and globally. Use a local variable to temporarily override the fail handler. This way the default fail handler is restored when the local variable goes out of scope, esp. when exceptions are thrown e.g. # Using a local variable to temporarily override the fail handler (preferred) { # new block - start of local scope local $XML::Checker::FAIL = \&my_fail; ... your code here ... } # end of block - the previous fail handler is restored You can also set the error handler globally, risking that your code may not be reusable or may clash with other modules that use XML::Checker. # Globally setting the fail handler (not recommended) $XML::Checker::FAIL = \&my_fail; ... rest of your code ... The fail handler is called with the following parameters ($code, $msg, @context), where $code is the error code, $msg is the error description and @context contains information on where the error occurred. The @context is a (ordered) list of (key,value) pairs and can easily be turned into a hash. It contains the following information: Element - tag name of Element node (if applicable) Attr - attribute name (if applicable) ChildElementIndex - if applicable (see error 157) line - only when parsing column - only when parsing byte - only when parsing (-1 means: end of file) Some examples of fail handlers: # Don't print info messages sub my_fail { my $code = shift; print STDERR XML::Checker::error_message ($code, @_) if $code < 300; } # Die when the first error is encountered - this will stop # the parsing process. Ignore information messages. sub my_fail { my $code = shift; die XML::Checker::error_message ($code, @_) if $code < 300; } # Count the number of undefined NOTATION references # and print the error as usual sub my_fail { my $code = shift; $count_undef_notations++ if $code == 100; XML::Checker::print_error ($code, @_); } # Die when an error is encountered. # Don't die if a warning or info message is encountered, just print a message. sub my_fail { my $code = shift; die XML::Checker::error_string ($code, @_) if $code < 200; XML::Checker::print_error ($code, @_); } =head1 INSIGNIFICANT WHITESPACE XML::Checker keeps track of whether whitespace found in character data is significant or not. It is considered insignicant if it is found inside an element that has a ELEMENT rule that is not of type Mixed or of type ANY. (A Mixed ELEMENT rule does contains the #PCDATA keyword. An ANY rule contains the ANY keyword. See the XML spec for more info.) XML::Checker can not determine whether whitespace is insignificant in those two cases, because they both allow regular character data to appear within XML elements and XML::Checker can therefore not deduce whether whitespace is part of the actual data or was just added for readability of the XML file. XML::Checker::Parser and XML::DOM::ValParser both have the option to skip insignificant whitespace when setting B to 1 in their constructor. If set, they will not call the Char handler when insignificant whitespace is encountered. This means that in XML::DOM::ValParser no Text nodes are created for insignificant whitespace. Regardless of whether the SkipInsignifWS options is set, XML::Checker always keeps track of whether whitespace is insignificant. After making a call to XML::Checker's Char handler, you can find out if it was insignificant whitespace by calling the isInsignifWS method. When using multiple (nested) XML::Checker instances or when using XML::Checker without using XML::Checker::Parser or XML::DOM::ValParser (which hardly anybody probably will), make sure to set a local variable in the scope of your checking code, e.g. { # new block - start of local scope local $XML::Checker::INSIGNIF_WS = 0; ... insert your code here ... } # end of scope =head1 ERROR CODES There are 3 categories, errors, warnings and info messages. (The codes are still subject to change, as well the error descriptions.) Most errors have a link to the appropriate Validaty Constraint (B) or other section in the XML specification. =head2 ERROR Messages =head2 100 - 109 =over 4 =item * B<100> - undefined NOTATION [$notation] in ATTLIST The ATTLIST contained a Notation reference that was not defined in a NOTATION definition. B L =item * B<101> - undefined ELEMENT [$tagName] The specified Element was never defined in an ELEMENT definition. This is not an error according to the XML spec. See L =item * B<102> - undefined unparsed ENTITY [$entity] The attribute value referenced an undefined unparsed entity. B L =item * B<103> - undefined attribute [$attrName] The specified attribute was not defined in an ATTLIST for that Element. B L =back =head2 110 - 119 =over 4 =item * B<110> - attribute [$attrName] of element [$tagName] already defined The specified attribute was already defined in this ATTLIST definition or in a previous one. This is not an error according to the XML spec. See L =item * B<111> - ID [$value] already defined An ID with the specified value was already defined in an attribute within the same document. B L =item * B<112> - unparsed ENTITY [$entity] already defined This is not an error according to the XML spec. See L =item * B<113> - NOTATION [$notation] already defined =item * B<114> - ENTITY [$entity] already defined This is not an error according to the XML spec. See L =item * B<115> - ELEMENT [$name] already defined B L =back =head2 120 - 129 =over 4 =item * B<120> - invalid default ENTITY [$default] (Or IDREF or NMTOKEN instead of ENTITY.) The ENTITY, IDREF or NMTOKEN reference in the default attribute value for an attribute with types ENTITY, IDREF or NMTOKEN was not valid. B L =item * B<121> - invalid default [$token] in ENTITIES [$default] (Or IDREFS or NMTOKENS instead of ENTITIES) One of the ENTITY, IDREF or NMTOKEN references in the default attribute value for an attribute with types ENTITIES, IDREFS or NMTOKENS was not valid. B L =item * B<122> - invalid default attribute value [$default] The specified default attribute value is not a valid attribute value. B L =item * B<123> - invalid default ID [$default], must be #REQUIRED or #IMPLIED The default attribute value for an attribute of type ID has to be #REQUIRED or #IMPLIED. B L =item * B<124> - bad model [$model] for ELEMENT [$name] The model in the ELEMENT definition did not conform to the XML syntax for Mixed models. See L =back =head2 130 - 139 =over 4 =item * B<130> - invalid NMTOKEN [$attrValue] The attribute value is not a valid NmToken token. B L =item * B<131> - invalid ID [$attrValue] The specified attribute value is not a valid Name token. B L =item * B<132> - invalid IDREF [$value] The specified attribute value is not a valid Name token. B L =item * B<133> - invalid ENTITY name [$name] The specified attribute value is not a valid Name token. B L =item * B<134> - invalid Enumeration value [$value] in ATTLIST The specified value is not a valid NmToken (see XML spec for def.) See definition of L =item * B<135> - empty NOTATION list in ATTLIST The NOTATION list of the ATTLIST definition did not contain any NOTATION references. See definition of L =item * B<136> - empty Enumeration list in ATTLIST The ATTLIST definition of the attribute of type Enumeration did not contain any values. See definition of L =item * B<137> - invalid ATTLIST type [$type] The attribute type has to be one of: ID, IDREF, IDREFS, ENTITY, ENTITIES, NMTOKEN, NMTOKENS, CDATA, NOTATION or an Enumeration. See definition of L =back =head2 149 - 159 =over 4 =item * B<149> - invalid text content [$value] A text was found in an element that should only include sub-elements The text is not made of non-significant whitespace. B<150> - bad #FIXED attribute value [$value], it should be [$default] The specified attribute was defined as #FIXED in the ATTLIST definition and the found attribute $value differs from the specified $default value. B L =item * B<151> - only one ID allowed in ATTLIST per element first=[$attrName] The ATTLIST definitions for an Element may contain only one attribute with the type ID. The specified $attrName is the one that was found first. B L =item * B<152> - Element should be EMPTY, found Element [$tagName] The ELEMENT definition for the specified Element said it should be EMPTY, but a child Element was found. B L =item * B<153> - Element should be EMPTY, found text [$text] The ELEMENT definition for the specified Element said it should be EMPTY, but text was found. Currently, whitespace is not allowed between the open and close tag. (This may be wrong, please give feedback.) To allow whitespace (subject to change), set: $XML::Checker::Context::EMPTY::ALLOW_WHITE_SPACE = 1; B L =item * B<154> - bad order of Elements Found=[$found] RE=[$re] The child elements of the specified Element did not match the regular expression found in the ELEMENT definition. $found contains a comma separated list of all the child element tag names that were found. $re contains the (decoded) regular expression that was used internally. B L =item * B<155> - more than one root Element [$tags] An XML Document may only contain one Element. $tags is a comma separated list of element tag names encountered sofar. L (expat) throws 'no element found' exception. See two_roots.xml for an example. See definition of L =item * B<156> - unexpected root Element [$tagName], expected [$rootTagName] The tag name of the root Element of the XML Document differs from the name specified in the DOCTYPE section. L (expat) throws 'not well-formed' exception. See bad_root.xml for an example. B L =item * B<157> - unexpected Element [$tagName] The ELEMENT definition for the specified Element does not allow child Elements with the specified $tagName. B L The error context contains ChildElementIndex which is the index within its parent Element (counting only Element nodes.) =item * B<158> - unspecified value for #IMPLIED attribute [$attrName] The ATTLIST for the specified attribute said the attribute was #IMPLIED, which means the user application should supply a value, but the attribute value was not specified. (User applications should pass a value and set $specified to 1 in the Attr handler.) =item * B<159> - unspecified value for #REQUIRED attribute [$attrName] The ATTLIST for the specified attribute said the attribute was #REQUIRED, which means that a value should have been specified. B L =back =head2 160 - 169 =over 4 =item * B<160> - invalid Enumeration value [$attrValue] The specified attribute value does not match one of the Enumeration values in the ATTLIST. B L =item * B<161> - invalid NOTATION value [$attrValue] The specifed attribute value was not found in the list of possible NOTATION references as found in the ATTLIST definition. B L =item * B<162> - undefined NOTATION [$attrValue] The NOTATION referenced by the specified attribute value was not defined. B L =back =head2 WARNING Messages (200 and up) =over 4 =item * B<200> - undefined ID [$id] was referenced [$n] times The specified ID was referenced $n times, but never defined in an attribute value with type ID. B L =back =head2 INFO Messages (300 and up) =over 4 =item * B<300> - [$n] references to ID [$id] The specified ID was referenced $n times. =back =head2 Not checked The following errors are already checked by L (expat) and are currently not checked by XML::Checker: (?? TODO - add more info) =over 4 =item root element is missing L (expat) throws 'no element found' exception. See no_root.xml for an example. =back =head1 XML::Checker XML::Checker can be easily plugged into your application. It uses mostly the same style of event handlers (or callbacks) as L. See L manual page for descriptions of most handlers. It also implements PerlSAX style event handlers. See L. Currently, the XML::Checker object is a blessed hash with the following (potentially useful) entries: $checker->{RootElement} - root element name as found in the DOCTYPE $checker->{NOTATION}->{$notation} - is 1 if the NOTATION was defined $checker->{ENTITY}->{$name} - contains the (first) ENTITY value if defined $checker->{Unparsed}->{$entity} - is 1 if the unparsed ENTITY was defined $checker->{ID}->{$id} - is 1 if the ID was defined $checker->{IDREF}->{$id} - number of times the ID was referenced # Less useful: $checker->{ERule}->{$tag} - the ELEMENT rules by Element tag name $checker->{ARule}->{$tag} - the ATTLIST rules by Element tag name $checker->{Context} - context stack used internally $checker->{CurrARule} - current ATTLIST rule for the current Element =head2 XML:Checker methods This section is only interesting when using XML::Checker directly. XML::Checker supports most event handlers that L supports with minor differences. Note that the XML::Checker event handler methods are instance methods and not static, so don't forget to call them like this, without passing $expat (as in the L) handlers: $checker->Start($tagName); =over 4 =item Constructor $checker = new XML::Checker; $checker = new XML::Checker (%user_args); User data may be stored by client applications. Only $checker->{User} is guaranteed not to clash with internal hash keys. =item getRootElement () $tagName = $checker->getRootElement; Returns the root element name as found in the DOCTYPE =back =head2 Expat interface XML::Checker supports what I call the I interface, which is the collection of methods you normally specify as the callback handlers when using XML::Parser. Only the following L handlers are currently supported: Init, Final, Char, Start, End, Element, Attlist, Doctype, Unparsed, Entity, Notation. I don't know how to correctly support the Default handler for all L releases. The Start handler works a little different (see below) and I added Attr, InitDomElem, FinalDomElem, CDATA and EntityRef handlers. See L for a description of the handlers that are not listed below. Note that this interface may disappear, when the PerlSAX interface stabilizes. =over 4 =item Start ($tag) $checker->Start($tag); Call this when an Element with the specified $tag name is encountered. Different from the Start handler in L, in that no attributes are passed in (use the Attr handler for those.) =item Attr ($tag, $attrName, $attrValue, $isSpecified) $checker->Attr($tag,$attrName,$attrValue,$spec); Checks an attribute with the specified $attrName and $attrValue against the ATTLIST definition of the element with the specified $tag name. $isSpecified means whether the attribute was specified (1) or defaulted (0). =item EndAttr () $checker->EndAttr; This should be called after all attributes are passed with Attr(). It will check which of the #REQUIRED attributes were not specified and generate the appropriate error (159) for each one that is missing. =item CDATA ($text) $checker->CDATA($text); This should be called whenever CDATASections are encountered. Similar to Char handler (but might perform different checks later...) =item EntityRef ($entity, $isParameterEntity) $checker->EntityRef($entity,$isParameterEntity); Checks the ENTITY reference. Set $isParameterEntity to 1 for entity references that start with '%'. =item InitDomElem () and FinalDomElem () Used by XML::DOM::Element::check() to initialize (and cleanup) the context stack when checking a single element. =back =head2 PerlSAX interface XML::Checker now also supports the PerlSAX interface, so you can use XML::Checker wherever you use PerlSAX handlers. XML::Checker implements the following methods: start_document, end_document, start_element, end_element, characters, processing_instruction, comment, start_cdata, end_cdata, entity_reference, notation_decl, unparsed_entity_decl, entity_decl, element_decl, attlist_decl, doctype_decl, xml_decl Not implemented: set_document_locator, ignorable_whitespace See PerlSAX.pod for details. (It is called lib/PerlSAX.pod in the libxml-perl distribution which can be found at CPAN.) =head1 CAVEATS This is an alpha release. It is not actively maintained, patches are accepted and incoporated in new releases, but that's about it. If you are interested in taking over maintimance of the module, email tjmather@tjmather.com. For a much faster, and correct DTD validator, see L. It uses the libxml2 library to validate DTD. =head1 AUTHOR Enno Derksen is the original author. Send patches to T.J. Mather at >. =head1 SEE ALSO L provides validating parsers against a DTD and is recommended over XML::Checker since it uses the libxml2 library which is fast and well-tested. The XML spec (Extensible Markup Language 1.0) at L The L and L manual pages. The other packages that come with XML::Checker: L, L The DOM Level 1 specification at L The PerlSAX specification. It is currently in lib/PerlSAX.pod in the libxml-perl distribution by Ken MacLeod. The original SAX specification (Simple API for XML) can be found at L and L XML-Checker-0.13/Changes0100644000076500007650000001613207537725326015206 0ustar tjmathertjmatherChange History: 0.13 (tjmather) 9/11/2002 - make parse return 1 (Steven Allen) - sub setModel: Generation of regexp goes wrong if an element has more than 62 members and any of these has cardinality other than 1: Parentheses are required around each re token, because the tokens are encoded as character pairs if there's 62 or more of them. (B Mills) 0.12 (tjmather) 4/22/2002 - Fixed bug with DTD alternation rules (Steven Allen) 0.11 (tjmather) 4/8/2002 - Corrected the token abbreviation sub (Philippe Verdret) - Added error 170, Element can't be empty (Philippe Verdret) - Added strict and warnings pragmas (Philippe Verdret) - Added two new tests, t/empty_elt.t and t/high_elt_number.t (Philippe Verdret) 0.10 (tjmather) 9/2/2001 - Fixed bug where checker didn't raise an error where a element that should have only contained sub-elements contained a text element (Michel Rodriguez) - Moved XML::DOM::ValParser into correct directory libxml-enno-1.04 (tjmather) 3/20/2001 - Fixed bug in XML::Checker::Parser with the setting @InterceptedHandlers (William Horka) - Fixed errors in test case t/chk_batch.t. Most had to do with change from "well-formed" to "well-formed (invalid token)" in error message. Also, the tests in chk_batch.t for the xml file attr3 did not return any errors any more, since XML::Parser >= 2.28 doesn't seem to call the entity handler more than once if a entity is repeated. - Updated t/chk_batch.t to be independent of the order of the error messages generated. This is because the order of the error messages seems to be dependent on the version of perl used (e.g. 5.005 vs. 5.6.0). libxml-enno-1.03 (enno) unreleased - Fixed errors in test case t/chk_batch.t for Windows. Most were related to differences in newlines. 0.09 in libxml-enno-1.01 (enno) 2/17/2000 - error 103 (undefined attribute) was not detected in all cases. (Thanks to Mark Hewis ) - error 103 - The error context used to contain the hash key 'Elem', but since all other errors use 'Element', this was changed to 'Element' as well. - The parsefile() method of XML::Checker::Parser now supports URLs. It uses LWP to download the remote file. See XML::Checker::Parser documentation for more info. - Fixed attlist_decl() handler to use 'ElementName' instead of 'EntityName'. 0.08 in libxml-enno-1.00 (enno) 10/26/1999 - XML::Checker moved to libxml-enno distribution. - XML::Checker now implements the PerlSAX Handler interface. - Fixed XML::Checker::Parser to use XML::Parser::Expat::specified_attr to determine which attributes were specified (and which were defaulted by expat.) (I was using original_string before and parsing the string myself to figure out which attributes were specified, but there was a bug in my code which would generate bogus error-159's.) (Thanks to Jim Anderson ) - External DTDs with relative file paths (and without the 'file://' prefix) are now located using SGML_SEARCH_PATH. See XML::Checker::Parser pod for details. (Thanks to Stephane Bortzmeyer ) - XML::Checker::DOM is now obsolete. I moved the functionality to XML::DOM. - The error descriptions in the XML::Checker manual page now have links to the appropriate sections and Validity Constraints in the XML spec. 0.07 (enno) 9/10/1999 - Fixed checking of NOTATION tokens in an ATTLIST. It would allow only valid XML Name ($ReName) values instead of NmTokens ($ReNmToken) (Thanks to Laurent Caprani ) - Added error 115: "ELEMENT [$name] already defined" (Thanks to Laurent Caprani ) - Added 'Element' to the error context of error 124 - Fixed checking of #REQUIRED attributes (error 159.) I had to add another handler to XML::Checker, called 'EndAttr', to support checking of #REQUIRED attributes. It should be called after all attributes are passed with Attr(). If the user forgets to call this method, missing #REQUIRED attributes (i.e. error 159) will not be generated. XML::Checker::Parser and XML::DOM::ValParser have been updated accordingly, so users of these classes don't need to make any code changes. Only people using XML::Checker directly have to add a call to EndAttr(). (Thanks to Jim Anderson ) - Default attribute values were stored in ARule as $arule->{$attr}->{Default}. This could wipe out other ARule fields (like Elem, Checker and Required) if your XML file contained attributes with those names. Now they are stored as $arule->{Default}->{$attr}. 0.06 (enno) 8/10/1999 - Added option to detect insignificant whitespace. See the section 'INSIGNIFICANT WHITESPACE' in the XML::Checker maual page and the SkipInsignifWS option in XML::Checker::Parser. - Added Comment handler to XML::Checker for completeness. It currently doesn't do anything. - Added t/filterInsignifWS.pl script that filters insignificant whitespace using XML::DOM::ValParser (see script for USAGE) 0.05 (enno) 8/2/1999 - Fixed the regular expressions for XML tokens to include Unicode values > 127 0.04 (enno) 6/29/1999 - Fixed splitting of Enumeration tokens in ATTLIST. It used to split the tokens with /\s+/, instead of /\s*\|\s*/ and it would produce error 134. (Thanks to Philippe Verdret ) - When parsing the external DTD in XML::Checker::Parser, the XML::Parser now copies the ErrorContext from the XML::Checker::Parser. (Thanks to Philippe Verdret ) - When parsing the external DTD in XML::Checker::Parser, it now prefixes the System ID with 'file:' because HTTP::Request is used to retrieve the external DTD and it expects 'file:' prefixes for file URLs. (Thanks to Stephane Bortzmeyer ) - It no longer generates error 156: unexpected root Element [doc], expected [] when no DTD is available and it doesn't know what the root element is. - Cleaned up some warnings when running with perl -w. (Thanks to Beau Simensen ) - Added CAVEATS section to XML::Checker::Parser POD regarding external DTDs. 0.03 (enno) 6/23/1999 - Fixed message 154 to print out better Buf and RE parameters. - Fixed the RE (regular expression) that is used to check valid element names. (Thanks to Matt Sergeant ) - Added code that reads external DTDs using LWP. This can be disabled by setting the XML::Checker property SkipExternalDTD. (Thanks to Matt Sergeant for writing the code!) 0.02 (enno) 5/28/1999 - Updated the regular expressions for the following tokens: Name, NmToken, AttValue. For now, I copied some of them from XML::DOM, but they should probably be in a separate module. (Thanks to John Posner ) - XML::DOM::EntityReference::expat_iter was using getName instead of getEntityName - fixed bugs in XML::Checker::EntityRef - XML::DOM::Notation::expat_iter was calling the Entity handler - implemented the XML::Checker::Entity method to check for duplicate ENTITY definitions and added error 114 - ENTITY [$entity] already defined - modified the test scripts to pass (KeepCDATA => 1, NoExpand => 1) to XML::Parser 0.01 (enno) 5/27/1999 - First release. XML-Checker-0.13/MANIFEST0100644000076500007650000000020107537725635015035 0ustar tjmathertjmatherChanges lib/XML/Checker.pm lib/XML/Checker/DOM.pm lib/XML/Checker/Parser.pm lib/XML/DOM/ValParser.pm Makefile.PL MANIFEST README XML-Checker-0.13/Makefile.PL0100644000076500007650000000055207314165202015644 0ustar tjmathertjmatheruse ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( 'NAME' => 'XML::Checker', 'VERSION_FROM' => 'lib/XML/Checker.pm', # finds $VERSION 'PREREQ_PM' => { 'XML::Parser' => '2.30', 'XML::Parser::PerlSAX' => '0.07', 'XML::DOM' => '1.29'} ); XML-Checker-0.13/t/0040775000076500007650000000000007454437201014146 5ustar tjmathertjmatherXML-Checker-0.13/t/chk1.xml0100664000076500007650000000024307000464450015503 0ustar tjmathertjmather ]> XML-Checker-0.13/t/chk_batch.t0100664000076500007650000001516607247513522016250 0ustar tjmathertjmather# # Usage: perl batch.t [-g] [-p pattern] # # -p pattern: Only runs the test cases for which the output filename # (e.g. t/out/dv_attr1.err) matches the specified pattern. # -g: Generates the t/out/*.err files (should probably only be # used by enno) # -d: If specified, generates 2 output files in t/out: # dv_attr1.err.out1 : result of test case # dv_attr1.err.out2 : expected output (same as .err with # normalized newlines) # -o: Also print the result of the test case. # # This script basically runs all test cases for all xml files in the t/ directory # and compares the output with the appropriate output in t/out/*.err # # There are currently 4 test cases: # - cp: Uses XML::Checker::Parser # - dc: Uses XML::DOM::Parser to create a XML::DOM::Document # and checks it with $doc->check. # - dv: uses XML::DOM::ValParser # - sc: Uses XML::Parser::PerlSAX to parse and # passes data onto the SAX interface of XML::Checker # # The expected output of running script 'cp' on file attr.xml can be found in # t/out/cp_attr1.err use strict; use Carp; use Getopt::Std; use Cwd; use vars qw( $opt_t $opt_g $opt_p $opt_d $opt_o ); # disable warnings with -w #$opt_o = $opt_d = $opt_t = $opt_g = $opt_p = undef; getopts ("dogt:p:"); # Determine OS path separator sub get_path_sep { if ((defined $^O and $^O =~ /MSWin32/i || $^O =~ /Windows_95/i || $^O =~ /Windows_NT/i) || (defined $ENV{OS} and $ENV{OS} =~ /MSWin32/i || $ENV{OS} =~ /Windows_95/i || $ENV{OS} =~ /Windows_NT/i)) { return "\\"; } elsif ((defined $^O and $^O =~ /MacOS/i) || (defined $ENV{OS} and $ENV{OS} =~ /MacOS/i)) { return ":"; } else # Unix { return "/"; } } sub slurp { my $file = shift; local $/; # slurp mode open (FILE, $file) || die "can't read $file"; my $str = ; close FILE; # Normalize newlines to Unix style $str =~ s/(\x0D\x0A|\x0D|\x0A)/\x0A/g; return $str; } my $sep = get_path_sep(); # chdir to the t/ subdirectory my $currdir = cwd; my $prefix = ""; if (-d 't') { chdir 't'; $prefix = "t$sep"; } my @xml = map { s/\.xml$//; $_ } <*.xml>; # strip .xml suffix chdir $currdir; my $GENERATE = $opt_g; my $ONLY = $opt_p || undef; my @scripts = qw( sc dv cp dc ); my $num_tests = @xml * @scripts; print "1..$num_tests\n"; my $testcase = 1; for my $script (@scripts) { for my $xml (@xml) { my $outfile = "${prefix}out${sep}${script}_$xml.err"; next if defined $ONLY && $outfile !~ /$ONLY/; # print "-- run $outfile\n"; my $err; { no strict "refs"; $err = &$script ($prefix . $xml); } if ($GENERATE) { if (open (OUT, ">$outfile")) { print OUT $err; close OUT; } else { print "(gen) could not open $outfile\n"; } } else { my $same = same ($err, $outfile); my $not = $same ? "" : "not "; print "${not}ok $testcase - $script/$xml\n"; } $testcase++; } } my $error_str = ""; sub my_fail { $error_str .= XML::Checker::error_string (@_); } sub append_str { $error_str .= shift() . "\n"; } sub same { my ($str, $outfile) = @_; if (open (FILE, $outfile)) { local $/; # temporarily set file slurping on my $str2 = || ""; close FILE; # Normalize newlines to current platform $str2 =~ s/(\x0D\x0A|\x0D|\x0A)/\n/g; # Different XML::Parser versions generate different 'byte' numbers # in their exceptions (e.g. some print 'byte -1' at the end of the # XML file, others print e.g. 'byte 42'), so here we simply # remove the byte number $str =~ s/byte\s\-?\d+//g; $str2 =~ s/byte\s\-?\d+//g; # Depending on the version of Perl (e.g. 5.005 vs. 5.6.0), # the order of the error messages is different, so here we # re-order the lines in alphabetical order $str = join("\n", sort split("\n",$str)); $str2 = join("\n", sort split("\n",$str2)); if ($opt_o) { print $str; } if ($str eq $str2) { return 1; } else { if ($opt_d) { open (OUT, ">$outfile.out1"); print OUT $str; close OUT; open (OUT, ">$outfile.out2"); print OUT $str2; close OUT; } return 0; } } else { print "ERROR: could not open $outfile: $?\n"; return 0; } } # XML::Parser throws exceptions of the form: # # no element found at line 5, column 0, byte -1 at # /home1/enno/perl500502/lib/site_perl/5.005/sun4-solaris/XML/Parser.pm line 168 # # For comparison purposes we have to chop off the filename, because that will # be different for each installation sub chop_exception { my ($ex) = @_; $ex =~ s/ at \S+ line \d+//; $ex; } # Script 'cp': Uses XML::Checker::Parser sub cp { my ($xml) = @_; require XML::Checker::Parser; local $XML::Checker::FAIL = \&my_fail; $error_str = ""; my $parser = new XML::Checker::Parser; eval { $parser->parse (slurp("$xml.xml")); }; if ($@) { $error_str .= "PARSER TERMINATED: " . chop_exception($@); } $error_str; } # Script 'dc': Uses XML::DOM::Parser to create a XML::DOM::Document # and checks it with $doc->check. sub dc { my ($xml) = @_; require XML::DOM; require XML::Checker; local $XML::Checker::FAIL = \&my_fail; local *XML::DOM::warning = \&append_str; $error_str = ""; my $parser = new XML::DOM::Parser; # could pass options! eval { my $doc = $parser->parse (slurp("$xml.xml")); $doc->check; # could pass Checker with options! $doc->dispose; }; if ($@) { $error_str .= "PARSER TERMINATED: " . chop_exception($@); } $error_str; } # Script 'dv': uses XML::DOM::ValParser sub dv { my ($xml) = @_; require XML::DOM; require XML::DOM::ValParser; local $XML::Checker::FAIL = \&my_fail; local *XML::DOM::warning = \&append_str; $error_str = ""; my $parser = new XML::DOM::ValParser; # could pass options! eval { my $doc = $parser->parse (slurp("$xml.xml")); $doc->dispose; }; if ($@) { $error_str .= "PARSER TERMINATED: " . chop_exception($@); } $error_str; } # Script 'sc': Uses XML::Parser::PerlSAX to parse and # passes data onto the SAX interface of XML::Checker sub sc { my ($xml) = @_; require XML::Parser::PerlSAX; require XML::Checker; local $XML::Checker::FAIL = \&my_fail; $error_str = ""; my $checker = new XML::Checker; # could pass options! my $parser = new XML::Parser::PerlSAX (Handler => $checker); if (open (STREAM, "$xml.xml")) { eval { $parser->parse (Source => { ByteStream => \*STREAM }); }; if ($@) { $error_str .= "PARSER TERMINATED: " . chop_exception($@); } close STREAM; } $error_str; } XML-Checker-0.13/t/out/0040775000076500007650000000000007444142142014751 5ustar tjmathertjmatherXML-Checker-0.13/t/out/cp_attr1.err0100664000076500007650000001272307223053676017212 0ustar tjmathertjmatherXML::Checker ERROR-100: undefined NOTATION [undef_notation] in ATTLIST Context: Element p, Attr notation, line 14, column 55, byte 362 XML::Checker ERROR-151: only one ID allowed per ELEMENT first=[req_id] Context: Element q, Attr second_id, line 21, column 16, byte 483 XML::Checker ERROR-120: invalid default NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def, line 27, column 19, byte 584 XML::Checker ERROR-123: invalid default ID [1bad_default_id], must be #REQUIRED or #IMPLIED Context: Element bad_id, Attr bad_default_id, line 38, column 21, byte 808 XML::Checker ERROR-120: invalid default IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref, line 39, column 27, byte 853 XML::Checker ERROR-121: invalid default [1bad_default_idrefs] in IDREFS [1bad_default_idrefs default_id] Context: Element bad_id, Attr bad_default_idrefs, line 40, column 29, byte 903 XML::Checker ERROR-120: invalid default ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 46, column 26, byte 1075 XML::Checker ERROR-121: invalid default [1bad_default_idref] in ENTITIES [1bad_default_idref default_entity] Context: Element bad_ent, Attr bad_default_ents, line 47, column 29, byte 1123 XML::Checker ERROR-110: attribute [dupl_attr] of element [dupl] already defined Context: Element dupl, Attr dupl_attr, line 53, column 18, byte 1249 XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id, line 60, column 1, byte 1300 XML::Checker ERROR-150: bad #FIXED attribute value [bad fixed value], it should be [fixed value] Context: Element p, Attr fixed, line 61, column 1, byte 1326 XML::Checker ERROR-160: invalid Enumeration value [bad enum] Context: Element p, Attr enum, line 61, column 1, byte 1326 XML::Checker ERROR-157: unexpected Element [unexpected] Context: ChildElementIndex 0, line 65, column 3, byte 1392 XML::Checker ERROR-157: unexpected Element [undefined] Context: ChildElementIndex 1, line 66, column 3, byte 1409 XML::Checker ERROR-101: undefined ELEMENT [undefined] Context: line 66, column 3, byte 1409 XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id, line 68, column 2, byte 1431 XML::Checker ERROR-130: invalid NMTOKEN [1bad nmtoken] Context: Element n, Attr nmtoken, line 70, column 1, byte 1468 XML::Checker ERROR-130: invalid NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def, line 70, column 1, byte 1468 XML::Checker ERROR-130: invalid NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def, line 71, column 1, byte 1497 XML::Checker ERROR-130: invalid NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def, line 72, column 1, byte 1529 XML::Checker ERROR-103: undefined attribute [bad_idref] Context: Element bad_id, line 76, column 1, byte 1608 XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id, line 76, column 1, byte 1608 XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref, line 76, column 1, byte 1608 XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs, line 76, column 1, byte 1608 XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id, line 77, column 1, byte 1639 XML::Checker ERROR-111: ID [1bad_default_id] already defined Context: Element bad_id, Attr bad_default_id, line 77, column 1, byte 1639 XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref, line 77, column 1, byte 1639 XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs, line 77, column 1, byte 1639 XML::Checker ERROR-103: undefined attribute [bad_ent] Context: Element bad_ent, line 78, column 1, byte 1650 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 78, column 1, byte 1650 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 78, column 1, byte 1650 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 78, column 1, byte 1650 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 78, column 1, byte 1650 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 79, column 1, byte 1684 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 79, column 1, byte 1684 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 79, column 1, byte 1684 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 79, column 1, byte 1684 XML::Checker ERROR-153: Element should be EMPTY, found text [text in empty] Context: line 80, column 8, byte 1703 XML::Checker WARNING-200: undefined ID [1bad_default_idrefs] was referenced [2] times XML::Checker WARNING-200: undefined ID [1bad_default_idref] was referenced [2] times XML::Checker INFO-300: [0] references to ID [1bad_default_id] XML::Checker INFO-300: [4] references to ID [default_id] XML::Checker INFO-300: [0] references to ID [unreferenced_id] XML-Checker-0.13/t/out/cp_attr2.err0100664000076500007650000000034307223053676017206 0ustar tjmathertjmatherXML::Checker ERROR-154: bad order of Elements Found=[a,b,c,a] RE=[((a)(b)(c))] Context: line 14, column 22, byte 227 XML::Checker ERROR-154: bad order of Elements Found=[c,c] RE=[((c))?] Context: line 17, column 14, byte 278 XML-Checker-0.13/t/out/cp_bad_root.err0100664000076500007650000000012107223053676017735 0ustar tjmathertjmatherPARSER TERMINATED: not well-formed (invalid token) at line 5, column 1, byte 43 XML-Checker-0.13/t/out/cp_chk1.err0100664000076500007650000000027607223053676017005 0ustar tjmathertjmatherXML::Checker ERROR-157: unexpected Element [d] Context: ChildElementIndex 0, line 12, column 3, byte 137 XML::Checker ERROR-101: undefined ELEMENT [d] Context: line 12, column 3, byte 137 XML-Checker-0.13/t/out/cp_entity.err0100664000076500007650000000012507223053676017464 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [root] Context: line 6, column 0, byte 47 XML-Checker-0.13/t/out/cp_fail.err0100664000076500007650000001130107223053676017061 0ustar tjmathertjmatherXML::Checker ERROR-100: undefined NOTATION [undef_notation] in ATTLIST Context: Element p, Attr notation, line 13, column 54, byte 420 XML::Checker ERROR-151: only one ID allowed per ELEMENT first=[req_id] Context: Element q, Attr second_id, line 18, column 15, byte 535 XML::Checker ERROR-123: invalid default ID [1bad_default_id], must be #REQUIRED or #IMPLIED Context: Element bad_id, Attr bad_default_id, line 23, column 20, byte 667 XML::Checker ERROR-120: invalid default IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref, line 24, column 26, byte 711 XML::Checker ERROR-121: invalid default [1bad_default_idrefs] in IDREFS [1bad_default_idrefs default_id] Context: Element bad_id, Attr bad_default_idrefs, line 25, column 28, byte 760 XML::Checker ERROR-120: invalid default ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 28, column 25, byte 864 XML::Checker ERROR-121: invalid default [1bad_default_idref] in ENTITIES [1bad_default_idref default_entity] Context: Element bad_ent, Attr bad_default_ents, line 29, column 28, byte 911 XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id, line 32, column 1, byte 959 XML::Checker ERROR-150: bad #FIXED attribute value [bad fixed value], it should be [fixed value] Context: Element p, Attr fixed, line 33, column 1, byte 985 XML::Checker ERROR-160: invalid Enumeration value [bad enum] Context: Element p, Attr enum, line 33, column 1, byte 985 XML::Checker ERROR-157: unexpected Element [unexpected] Context: ChildElementIndex 0, line 37, column 3, byte 1051 XML::Checker ERROR-157: unexpected Element [undefined] Context: ChildElementIndex 1, line 38, column 3, byte 1068 XML::Checker ERROR-101: undefined ELEMENT [undefined] Context: line 38, column 3, byte 1068 XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id, line 40, column 2, byte 1090 XML::Checker ERROR-130: invalid NMTOKEN [1bad nmtoken] Context: Element n, Attr nmtoken, line 42, column 1, byte 1127 XML::Checker ERROR-103: undefined attribute [bad_idref] Context: Element bad_id, line 44, column 1, byte 1186 XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id, line 44, column 1, byte 1186 XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref, line 44, column 1, byte 1186 XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs, line 44, column 1, byte 1186 XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id, line 45, column 1, byte 1217 XML::Checker ERROR-111: ID [1bad_default_id] already defined Context: Element bad_id, Attr bad_default_id, line 45, column 1, byte 1217 XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref, line 45, column 1, byte 1217 XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs, line 45, column 1, byte 1217 XML::Checker ERROR-103: undefined attribute [bad_ent] Context: Element bad_ent, line 46, column 1, byte 1228 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 46, column 1, byte 1228 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 46, column 1, byte 1228 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 46, column 1, byte 1228 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 46, column 1, byte 1228 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 47, column 1, byte 1262 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 47, column 1, byte 1262 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 47, column 1, byte 1262 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 47, column 1, byte 1262 XML::Checker WARNING-200: undefined ID [1bad_default_idrefs] was referenced [2] times XML::Checker WARNING-200: undefined ID [1bad_default_idref] was referenced [2] times XML::Checker INFO-300: [0] references to ID [1bad_default_id] XML::Checker INFO-300: [4] references to ID [default_id] XML::Checker INFO-300: [0] references to ID [unreferenced_id] XML-Checker-0.13/t/out/cp_insignif_ws.err0100664000076500007650000000056307223053676020475 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [a] Context: line 9, column 2, byte 176 XML::Checker ERROR-101: undefined ELEMENT [b] Context: line 10, column 2, byte 188 XML::Checker ERROR-153: Element should be EMPTY, found text [ ] Context: line 12, column 4, byte 208 XML::Checker ERROR-153: Element should be EMPTY, found text [ ] Context: line 13, column 0, byte 209 XML-Checker-0.13/t/out/cp_no_root.err0100664000076500007650000000010207223053676017622 0ustar tjmathertjmatherPARSER TERMINATED: no element found at line 5, column 0, byte 42 XML-Checker-0.13/t/out/cp_nodtd.err0100664000076500007650000000025007223053676017257 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [doc] Context: line 1, column 0, byte 0 XML::Checker ERROR-101: undefined ELEMENT [elem] Context: line 3, column 1, byte 47 XML-Checker-0.13/t/out/cp_required_attr.err0100664000076500007650000000021007223053676021015 0ustar tjmathertjmatherXML::Checker ERROR-159: unspecified value for #REQUIRED attribute [NAME] Context: Element TEST, Attr NAME, line 11, column 0, byte 126 XML-Checker-0.13/t/out/cp_test.err0100664000076500007650000000041307223053676017127 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [doc] Context: line 1, column 0, byte 0 XML::Checker ERROR-101: undefined ELEMENT [elem] Context: line 2, column 1, byte 7 XML::Checker ERROR-103: undefined attribute [attr] Context: Element elem, line 2, column 1, byte 7 XML-Checker-0.13/t/out/cp_two_elem_defs.err0100664000076500007650000000027107223053676020766 0ustar tjmathertjmatherXML::Checker ERROR-115: ELEMENT [b] already defined Context: Element b, line 3, column 21, byte 58 XML::Checker ERROR-101: undefined ELEMENT [root] Context: line 5, column 0, byte 64 XML-Checker-0.13/t/out/cp_two_roots.err0100664000076500007650000000012107223053676020203 0ustar tjmathertjmatherPARSER TERMINATED: not well-formed (invalid token) at line 5, column 1, byte 43 XML-Checker-0.13/t/out/dc_attr1.err0100664000076500007650000001102607223053676017171 0ustar tjmathertjmathermultiple definitions of attribute dupl_attr for element dupl, only first one is recognized XML::Checker ERROR-100: undefined NOTATION [undef_notation] in ATTLIST Context: Element p, Attr notation XML::Checker ERROR-151: only one ID allowed per ELEMENT first=[req_id] Context: Element q, Attr second_id XML::Checker ERROR-120: invalid default NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def XML::Checker ERROR-123: invalid default ID [1bad_default_id], must be #REQUIRED or #IMPLIED Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-120: invalid default IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref XML::Checker ERROR-121: invalid default [1bad_default_idrefs] in IDREFS [1bad_default_idrefs default_id] Context: Element bad_id, Attr bad_default_idrefs XML::Checker ERROR-120: invalid default ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-121: invalid default [1bad_default_idref] in ENTITIES [1bad_default_idref default_entity] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id XML::Checker ERROR-150: bad #FIXED attribute value [bad fixed value], it should be [fixed value] Context: Element p, Attr fixed XML::Checker ERROR-160: invalid Enumeration value [bad enum] Context: Element p, Attr enum XML::Checker ERROR-157: unexpected Element [unexpected] Context: ChildElementIndex 0 XML::Checker ERROR-157: unexpected Element [undefined] Context: ChildElementIndex 1 XML::Checker ERROR-101: undefined ELEMENT [undefined] XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id XML::Checker ERROR-130: invalid NMTOKEN [1bad nmtoken] Context: Element n, Attr nmtoken XML::Checker ERROR-130: invalid NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def XML::Checker ERROR-130: invalid NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def XML::Checker ERROR-130: invalid NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def XML::Checker ERROR-103: undefined attribute [bad_idref] Context: Element bad_id XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-111: ID [1bad_default_id] already defined Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs XML::Checker ERROR-103: undefined attribute [bad_ent] Context: Element bad_ent XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-102: undefined unparsed ENTITY [default_entity] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-102: undefined unparsed ENTITY [default_entity] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-153: Element should be EMPTY, found text [text in empty] XML::Checker WARNING-200: undefined ID [1bad_default_idrefs] was referenced [2] times XML::Checker WARNING-200: undefined ID [1bad_default_idref] was referenced [2] times XML::Checker INFO-300: [0] references to ID [1bad_default_id] XML::Checker INFO-300: [4] references to ID [default_id] XML::Checker INFO-300: [0] references to ID [unreferenced_id] XML-Checker-0.13/t/out/dc_attr2.err0100664000076500007650000000022507223053676017171 0ustar tjmathertjmatherXML::Checker ERROR-154: bad order of Elements Found=[a,b,c,a] RE=[((a)(b)(c))] XML::Checker ERROR-154: bad order of Elements Found=[c,c] RE=[((c))?] XML-Checker-0.13/t/out/dc_bad_root.err0100664000076500007650000000012107223053676017721 0ustar tjmathertjmatherPARSER TERMINATED: not well-formed (invalid token) at line 5, column 1, byte 43 XML-Checker-0.13/t/out/dc_chk1.err0100664000076500007650000000017307223053676016765 0ustar tjmathertjmatherXML::Checker ERROR-157: unexpected Element [d] Context: ChildElementIndex 0 XML::Checker ERROR-101: undefined ELEMENT [d] XML-Checker-0.13/t/out/dc_entity.err0100664000076500007650000000006107223053676017447 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [root] XML-Checker-0.13/t/out/dc_fail.err0100664000076500007650000000774307223053676017064 0ustar tjmathertjmatherXML::Checker ERROR-100: undefined NOTATION [undef_notation] in ATTLIST Context: Element p, Attr notation XML::Checker ERROR-151: only one ID allowed per ELEMENT first=[req_id] Context: Element q, Attr second_id XML::Checker ERROR-123: invalid default ID [1bad_default_id], must be #REQUIRED or #IMPLIED Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-120: invalid default IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref XML::Checker ERROR-121: invalid default [1bad_default_idrefs] in IDREFS [1bad_default_idrefs default_id] Context: Element bad_id, Attr bad_default_idrefs XML::Checker ERROR-120: invalid default ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-121: invalid default [1bad_default_idref] in ENTITIES [1bad_default_idref default_entity] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id XML::Checker ERROR-150: bad #FIXED attribute value [bad fixed value], it should be [fixed value] Context: Element p, Attr fixed XML::Checker ERROR-160: invalid Enumeration value [bad enum] Context: Element p, Attr enum XML::Checker ERROR-157: unexpected Element [unexpected] Context: ChildElementIndex 0 XML::Checker ERROR-157: unexpected Element [undefined] Context: ChildElementIndex 1 XML::Checker ERROR-101: undefined ELEMENT [undefined] XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id XML::Checker ERROR-130: invalid NMTOKEN [1bad nmtoken] Context: Element n, Attr nmtoken XML::Checker ERROR-103: undefined attribute [bad_idref] Context: Element bad_id XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-111: ID [1bad_default_id] already defined Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs XML::Checker ERROR-103: undefined attribute [bad_ent] Context: Element bad_ent XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-102: undefined unparsed ENTITY [default_entity] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-102: undefined unparsed ENTITY [default_entity] Context: Element bad_ent, Attr bad_default_ents XML::Checker WARNING-200: undefined ID [1bad_default_idrefs] was referenced [2] times XML::Checker WARNING-200: undefined ID [1bad_default_idref] was referenced [2] times XML::Checker INFO-300: [0] references to ID [1bad_default_id] XML::Checker INFO-300: [4] references to ID [default_id] XML::Checker INFO-300: [0] references to ID [unreferenced_id] XML-Checker-0.13/t/out/dc_insignif_ws.err0100664000076500007650000000023507223053676020455 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [a] XML::Checker ERROR-101: undefined ELEMENT [b] XML::Checker ERROR-153: Element should be EMPTY, found text [ ] XML-Checker-0.13/t/out/dc_no_root.err0100664000076500007650000000010207223053676017606 0ustar tjmathertjmatherPARSER TERMINATED: no element found at line 5, column 0, byte 42 XML-Checker-0.13/t/out/dc_nodtd.err0100664000076500007650000000014107223053676017242 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [doc] XML::Checker ERROR-101: undefined ELEMENT [elem] XML-Checker-0.13/t/out/dc_required_attr.err0100664000076500007650000000015307223053676021007 0ustar tjmathertjmatherXML::Checker ERROR-159: unspecified value for #REQUIRED attribute [NAME] Context: Element TEST, Attr NAME XML-Checker-0.13/t/out/dc_test.err0100664000076500007650000000025307223053676017115 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [doc] XML::Checker ERROR-101: undefined ELEMENT [elem] XML::Checker ERROR-103: undefined attribute [attr] Context: Element elem XML-Checker-0.13/t/out/dc_two_elem_defs.err0100664000076500007650000000006107223053676020747 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [root] XML-Checker-0.13/t/out/dc_two_roots.err0100664000076500007650000000012107223053676020167 0ustar tjmathertjmatherPARSER TERMINATED: not well-formed (invalid token) at line 5, column 1, byte 43 XML-Checker-0.13/t/out/dv_attr1.err0100664000076500007650000001305607223053676017221 0ustar tjmathertjmatherXML::Checker ERROR-100: undefined NOTATION [undef_notation] in ATTLIST Context: Element p, Attr notation, line 14, column 55, byte 362 XML::Checker ERROR-151: only one ID allowed per ELEMENT first=[req_id] Context: Element q, Attr second_id, line 21, column 16, byte 483 XML::Checker ERROR-120: invalid default NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def, line 27, column 19, byte 584 XML::Checker ERROR-123: invalid default ID [1bad_default_id], must be #REQUIRED or #IMPLIED Context: Element bad_id, Attr bad_default_id, line 38, column 21, byte 808 XML::Checker ERROR-120: invalid default IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref, line 39, column 27, byte 853 XML::Checker ERROR-121: invalid default [1bad_default_idrefs] in IDREFS [1bad_default_idrefs default_id] Context: Element bad_id, Attr bad_default_idrefs, line 40, column 29, byte 903 XML::Checker ERROR-120: invalid default ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 46, column 26, byte 1075 XML::Checker ERROR-121: invalid default [1bad_default_idref] in ENTITIES [1bad_default_idref default_entity] Context: Element bad_ent, Attr bad_default_ents, line 47, column 29, byte 1123 XML::Checker ERROR-110: attribute [dupl_attr] of element [dupl] already defined Context: Element dupl, Attr dupl_attr, line 53, column 18, byte 1249 multiple definitions of attribute dupl_attr for element dupl, only first one is recognized XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id, line 60, column 1, byte 1300 XML::Checker ERROR-150: bad #FIXED attribute value [bad fixed value], it should be [fixed value] Context: Element p, Attr fixed, line 61, column 1, byte 1326 XML::Checker ERROR-160: invalid Enumeration value [bad enum] Context: Element p, Attr enum, line 61, column 1, byte 1326 XML::Checker ERROR-157: unexpected Element [unexpected] Context: ChildElementIndex 0, line 65, column 3, byte 1392 XML::Checker ERROR-157: unexpected Element [undefined] Context: ChildElementIndex 1, line 66, column 3, byte 1409 XML::Checker ERROR-101: undefined ELEMENT [undefined] Context: line 66, column 3, byte 1409 XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id, line 68, column 2, byte 1431 XML::Checker ERROR-130: invalid NMTOKEN [1bad nmtoken] Context: Element n, Attr nmtoken, line 70, column 1, byte 1468 XML::Checker ERROR-130: invalid NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def, line 70, column 1, byte 1468 XML::Checker ERROR-130: invalid NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def, line 71, column 1, byte 1497 XML::Checker ERROR-130: invalid NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def, line 72, column 1, byte 1529 XML::Checker ERROR-103: undefined attribute [bad_idref] Context: Element bad_id, line 76, column 1, byte 1608 XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id, line 76, column 1, byte 1608 XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref, line 76, column 1, byte 1608 XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs, line 76, column 1, byte 1608 XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id, line 77, column 1, byte 1639 XML::Checker ERROR-111: ID [1bad_default_id] already defined Context: Element bad_id, Attr bad_default_id, line 77, column 1, byte 1639 XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref, line 77, column 1, byte 1639 XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs, line 77, column 1, byte 1639 XML::Checker ERROR-103: undefined attribute [bad_ent] Context: Element bad_ent, line 78, column 1, byte 1650 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 78, column 1, byte 1650 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 78, column 1, byte 1650 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 78, column 1, byte 1650 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 78, column 1, byte 1650 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 79, column 1, byte 1684 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 79, column 1, byte 1684 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 79, column 1, byte 1684 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 79, column 1, byte 1684 XML::Checker ERROR-153: Element should be EMPTY, found text [text in empty] Context: line 80, column 8, byte 1703 XML::Checker WARNING-200: undefined ID [1bad_default_idrefs] was referenced [2] times XML::Checker WARNING-200: undefined ID [1bad_default_idref] was referenced [2] times XML::Checker INFO-300: [0] references to ID [1bad_default_id] XML::Checker INFO-300: [4] references to ID [default_id] XML::Checker INFO-300: [0] references to ID [unreferenced_id] XML-Checker-0.13/t/out/dv_attr2.err0100664000076500007650000000034307223053676017215 0ustar tjmathertjmatherXML::Checker ERROR-154: bad order of Elements Found=[a,b,c,a] RE=[((a)(b)(c))] Context: line 14, column 22, byte 227 XML::Checker ERROR-154: bad order of Elements Found=[c,c] RE=[((c))?] Context: line 17, column 14, byte 278 XML-Checker-0.13/t/out/dv_bad_root.err0100664000076500007650000000012107223053676017744 0ustar tjmathertjmatherPARSER TERMINATED: not well-formed (invalid token) at line 5, column 1, byte 43 XML-Checker-0.13/t/out/dv_chk1.err0100664000076500007650000000027607223053676017014 0ustar tjmathertjmatherXML::Checker ERROR-157: unexpected Element [d] Context: ChildElementIndex 0, line 12, column 3, byte 137 XML::Checker ERROR-101: undefined ELEMENT [d] Context: line 12, column 3, byte 137 XML-Checker-0.13/t/out/dv_entity.err0100664000076500007650000000012507223053676017473 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [root] Context: line 6, column 0, byte 47 XML-Checker-0.13/t/out/dv_fail.err0100664000076500007650000001130107223053676017070 0ustar tjmathertjmatherXML::Checker ERROR-100: undefined NOTATION [undef_notation] in ATTLIST Context: Element p, Attr notation, line 13, column 54, byte 420 XML::Checker ERROR-151: only one ID allowed per ELEMENT first=[req_id] Context: Element q, Attr second_id, line 18, column 15, byte 535 XML::Checker ERROR-123: invalid default ID [1bad_default_id], must be #REQUIRED or #IMPLIED Context: Element bad_id, Attr bad_default_id, line 23, column 20, byte 667 XML::Checker ERROR-120: invalid default IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref, line 24, column 26, byte 711 XML::Checker ERROR-121: invalid default [1bad_default_idrefs] in IDREFS [1bad_default_idrefs default_id] Context: Element bad_id, Attr bad_default_idrefs, line 25, column 28, byte 760 XML::Checker ERROR-120: invalid default ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 28, column 25, byte 864 XML::Checker ERROR-121: invalid default [1bad_default_idref] in ENTITIES [1bad_default_idref default_entity] Context: Element bad_ent, Attr bad_default_ents, line 29, column 28, byte 911 XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id, line 32, column 1, byte 959 XML::Checker ERROR-150: bad #FIXED attribute value [bad fixed value], it should be [fixed value] Context: Element p, Attr fixed, line 33, column 1, byte 985 XML::Checker ERROR-160: invalid Enumeration value [bad enum] Context: Element p, Attr enum, line 33, column 1, byte 985 XML::Checker ERROR-157: unexpected Element [unexpected] Context: ChildElementIndex 0, line 37, column 3, byte 1051 XML::Checker ERROR-157: unexpected Element [undefined] Context: ChildElementIndex 1, line 38, column 3, byte 1068 XML::Checker ERROR-101: undefined ELEMENT [undefined] Context: line 38, column 3, byte 1068 XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id, line 40, column 2, byte 1090 XML::Checker ERROR-130: invalid NMTOKEN [1bad nmtoken] Context: Element n, Attr nmtoken, line 42, column 1, byte 1127 XML::Checker ERROR-103: undefined attribute [bad_idref] Context: Element bad_id, line 44, column 1, byte 1186 XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id, line 44, column 1, byte 1186 XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref, line 44, column 1, byte 1186 XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs, line 44, column 1, byte 1186 XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id, line 45, column 1, byte 1217 XML::Checker ERROR-111: ID [1bad_default_id] already defined Context: Element bad_id, Attr bad_default_id, line 45, column 1, byte 1217 XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref, line 45, column 1, byte 1217 XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs, line 45, column 1, byte 1217 XML::Checker ERROR-103: undefined attribute [bad_ent] Context: Element bad_ent, line 46, column 1, byte 1228 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 46, column 1, byte 1228 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 46, column 1, byte 1228 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 46, column 1, byte 1228 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 46, column 1, byte 1228 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 47, column 1, byte 1262 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent, line 47, column 1, byte 1262 XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 47, column 1, byte 1262 XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents, line 47, column 1, byte 1262 XML::Checker WARNING-200: undefined ID [1bad_default_idrefs] was referenced [2] times XML::Checker WARNING-200: undefined ID [1bad_default_idref] was referenced [2] times XML::Checker INFO-300: [0] references to ID [1bad_default_id] XML::Checker INFO-300: [4] references to ID [default_id] XML::Checker INFO-300: [0] references to ID [unreferenced_id] XML-Checker-0.13/t/out/dv_insignif_ws.err0100664000076500007650000000056307223053676020504 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [a] Context: line 9, column 2, byte 176 XML::Checker ERROR-101: undefined ELEMENT [b] Context: line 10, column 2, byte 188 XML::Checker ERROR-153: Element should be EMPTY, found text [ ] Context: line 12, column 4, byte 208 XML::Checker ERROR-153: Element should be EMPTY, found text [ ] Context: line 13, column 0, byte 209 XML-Checker-0.13/t/out/dv_no_root.err0100664000076500007650000000010207223053676017631 0ustar tjmathertjmatherPARSER TERMINATED: no element found at line 5, column 0, byte 42 XML-Checker-0.13/t/out/dv_nodtd.err0100664000076500007650000000025007223053676017266 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [doc] Context: line 1, column 0, byte 0 XML::Checker ERROR-101: undefined ELEMENT [elem] Context: line 3, column 1, byte 47 XML-Checker-0.13/t/out/dv_required_attr.err0100664000076500007650000000021007223053676021024 0ustar tjmathertjmatherXML::Checker ERROR-159: unspecified value for #REQUIRED attribute [NAME] Context: Element TEST, Attr NAME, line 11, column 0, byte 126 XML-Checker-0.13/t/out/dv_test.err0100664000076500007650000000041307223053676017136 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [doc] Context: line 1, column 0, byte 0 XML::Checker ERROR-101: undefined ELEMENT [elem] Context: line 2, column 1, byte 7 XML::Checker ERROR-103: undefined attribute [attr] Context: Element elem, line 2, column 1, byte 7 XML-Checker-0.13/t/out/dv_two_elem_defs.err0100664000076500007650000000027107223053676020775 0ustar tjmathertjmatherXML::Checker ERROR-115: ELEMENT [b] already defined Context: Element b, line 3, column 21, byte 58 XML::Checker ERROR-101: undefined ELEMENT [root] Context: line 5, column 0, byte 64 XML-Checker-0.13/t/out/dv_two_roots.err0100664000076500007650000000012107223053676020212 0ustar tjmathertjmatherPARSER TERMINATED: not well-formed (invalid token) at line 5, column 1, byte 43 XML-Checker-0.13/t/out/sc_attr1.err0100664000076500007650000001051207223053676017207 0ustar tjmathertjmatherXML::Checker ERROR-100: undefined NOTATION [undef_notation] in ATTLIST Context: Element p, Attr notation XML::Checker ERROR-151: only one ID allowed per ELEMENT first=[req_id] Context: Element q, Attr second_id XML::Checker ERROR-120: invalid default NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def XML::Checker ERROR-123: invalid default ID [1bad_default_id], must be #REQUIRED or #IMPLIED Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-120: invalid default IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref XML::Checker ERROR-121: invalid default [1bad_default_idrefs] in IDREFS [1bad_default_idrefs default_id] Context: Element bad_id, Attr bad_default_idrefs XML::Checker ERROR-120: invalid default ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-121: invalid default [1bad_default_idref] in ENTITIES [1bad_default_idref default_entity] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-110: attribute [dupl_attr] of element [dupl] already defined Context: Element dupl, Attr dupl_attr XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id XML::Checker ERROR-150: bad #FIXED attribute value [bad fixed value], it should be [fixed value] Context: Element p, Attr fixed XML::Checker ERROR-160: invalid Enumeration value [bad enum] Context: Element p, Attr enum XML::Checker ERROR-157: unexpected Element [unexpected] Context: ChildElementIndex 0 XML::Checker ERROR-157: unexpected Element [undefined] Context: ChildElementIndex 1 XML::Checker ERROR-101: undefined ELEMENT [undefined] XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id XML::Checker ERROR-130: invalid NMTOKEN [1bad nmtoken] Context: Element n, Attr nmtoken XML::Checker ERROR-130: invalid NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def XML::Checker ERROR-130: invalid NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def XML::Checker ERROR-130: invalid NMTOKEN [1bad default nmtoken] Context: Element n, Attr bad_def XML::Checker ERROR-103: undefined attribute [bad_idref] Context: Element bad_id XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-111: ID [1bad_default_id] already defined Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-103: undefined attribute [bad_ent] Context: Element bad_ent XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-153: Element should be EMPTY, found text [text in empty] XML::Checker WARNING-200: undefined ID [1bad_default_idrefs] was referenced [2] times XML::Checker WARNING-200: undefined ID [1bad_default_idref] was referenced [2] times XML::Checker INFO-300: [0] references to ID [1bad_default_id] XML::Checker INFO-300: [4] references to ID [default_id] XML::Checker INFO-300: [0] references to ID [unreferenced_id] XML-Checker-0.13/t/out/sc_attr2.err0100664000076500007650000000022507223053676017210 0ustar tjmathertjmatherXML::Checker ERROR-154: bad order of Elements Found=[a,b,c,a] RE=[((a)(b)(c))] XML::Checker ERROR-154: bad order of Elements Found=[c,c] RE=[((c))?] XML-Checker-0.13/t/out/sc_bad_root.err0100664000076500007650000000012107223053676017740 0ustar tjmathertjmatherPARSER TERMINATED: not well-formed (invalid token) at line 5, column 1, byte 43 XML-Checker-0.13/t/out/sc_chk1.err0100664000076500007650000000017307223053676017004 0ustar tjmathertjmatherXML::Checker ERROR-157: unexpected Element [d] Context: ChildElementIndex 0 XML::Checker ERROR-101: undefined ELEMENT [d] XML-Checker-0.13/t/out/sc_entity.err0100664000076500007650000000006107223053676017466 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [root] XML-Checker-0.13/t/out/sc_fail.err0100664000076500007650000000737307223053676017102 0ustar tjmathertjmatherXML::Checker ERROR-100: undefined NOTATION [undef_notation] in ATTLIST Context: Element p, Attr notation XML::Checker ERROR-151: only one ID allowed per ELEMENT first=[req_id] Context: Element q, Attr second_id XML::Checker ERROR-123: invalid default ID [1bad_default_id], must be #REQUIRED or #IMPLIED Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-120: invalid default IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref XML::Checker ERROR-121: invalid default [1bad_default_idrefs] in IDREFS [1bad_default_idrefs default_id] Context: Element bad_id, Attr bad_default_idrefs XML::Checker ERROR-120: invalid default ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-121: invalid default [1bad_default_idref] in ENTITIES [1bad_default_idref default_entity] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id XML::Checker ERROR-150: bad #FIXED attribute value [bad fixed value], it should be [fixed value] Context: Element p, Attr fixed XML::Checker ERROR-160: invalid Enumeration value [bad enum] Context: Element p, Attr enum XML::Checker ERROR-157: unexpected Element [unexpected] Context: ChildElementIndex 0 XML::Checker ERROR-157: unexpected Element [undefined] Context: ChildElementIndex 1 XML::Checker ERROR-101: undefined ELEMENT [undefined] XML::Checker ERROR-159: unspecified value for #REQUIRED attribute [second_id] Context: Element q, Attr second_id XML::Checker ERROR-130: invalid NMTOKEN [1bad nmtoken] Context: Element n, Attr nmtoken XML::Checker ERROR-103: undefined attribute [bad_idref] Context: Element bad_id XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-132: invalid IDREF [1bad_default_idref] Context: Element bad_id, Attr bad_default_idref XML::Checker ERROR-132: invalid IDREF [1bad_default_idrefs] Context: Element bad_id, Attr bad_default_idrefs XML::Checker ERROR-131: invalid ID [1bad_default_id] Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-111: ID [1bad_default_id] already defined Context: Element bad_id, Attr bad_default_id XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-103: undefined attribute [bad_ent] Context: Element bad_ent XML::Checker ERROR-133: invalid ENTITY name [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_ent] Context: Element bad_ent, Attr bad_default_ent XML::Checker ERROR-133: invalid ENTITY name [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker ERROR-102: undefined unparsed ENTITY [1bad_default_idref] Context: Element bad_ent, Attr bad_default_ents XML::Checker WARNING-200: undefined ID [1bad_default_idrefs] was referenced [2] times XML::Checker WARNING-200: undefined ID [1bad_default_idref] was referenced [2] times XML::Checker INFO-300: [0] references to ID [1bad_default_id] XML::Checker INFO-300: [4] references to ID [default_id] XML::Checker INFO-300: [0] references to ID [unreferenced_id] XML-Checker-0.13/t/out/sc_insignif_ws.err0100664000076500007650000000033407223053676020474 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [a] XML::Checker ERROR-101: undefined ELEMENT [b] XML::Checker ERROR-153: Element should be EMPTY, found text [ ] XML::Checker ERROR-153: Element should be EMPTY, found text [ ] XML-Checker-0.13/t/out/sc_no_root.err0100664000076500007650000000010207223053676017625 0ustar tjmathertjmatherPARSER TERMINATED: no element found at line 5, column 0, byte 42 XML-Checker-0.13/t/out/sc_nodtd.err0100664000076500007650000000014107223053676017261 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [doc] XML::Checker ERROR-101: undefined ELEMENT [elem] XML-Checker-0.13/t/out/sc_required_attr.err0100664000076500007650000000015307223053676021026 0ustar tjmathertjmatherXML::Checker ERROR-159: unspecified value for #REQUIRED attribute [NAME] Context: Element TEST, Attr NAME XML-Checker-0.13/t/out/sc_test.err0100664000076500007650000000025307223053676017134 0ustar tjmathertjmatherXML::Checker ERROR-101: undefined ELEMENT [doc] XML::Checker ERROR-101: undefined ELEMENT [elem] XML::Checker ERROR-103: undefined attribute [attr] Context: Element elem XML-Checker-0.13/t/out/sc_two_elem_defs.err0100664000076500007650000000017107223053676020770 0ustar tjmathertjmatherXML::Checker ERROR-115: ELEMENT [b] already defined Context: Element b XML::Checker ERROR-101: undefined ELEMENT [root] XML-Checker-0.13/t/out/sc_two_roots.err0100664000076500007650000000012107223053676020206 0ustar tjmathertjmatherPARSER TERMINATED: not well-formed (invalid token) at line 5, column 1, byte 43 XML-Checker-0.13/t/out/cp_attr3.err0100664000076500007650000000000007223053676017175 0ustar tjmathertjmatherXML-Checker-0.13/t/out/dc_attr3.err0100664000076500007650000000000007223053676017161 0ustar tjmathertjmatherXML-Checker-0.13/t/out/dv_attr3.err0100664000076500007650000000000007223053676017204 0ustar tjmathertjmatherXML-Checker-0.13/t/out/sc_attr3.err0100664000076500007650000000000007223053676017200 0ustar tjmathertjmatherXML-Checker-0.13/t/attr1.xml0100664000076500007650000000330507314164430015715 0ustar tjmathertjmather ]>

text in empty
XML-Checker-0.13/t/attr2.xml0100664000076500007650000000044507314164430015720 0ustar tjmathertjmather ]> XML-Checker-0.13/t/attr3.xml0100664000076500007650000000063507314164430015722 0ustar tjmathertjmather ]> Entity ref &ent; in text
XML-Checker-0.13/t/bad_root.xml0100664000076500007650000000006607314164430016454 0ustar tjmathertjmather ]> XML-Checker-0.13/t/entity.xml0100664000076500007650000000007607314164430016200 0ustar tjmathertjmather ]> XML-Checker-0.13/t/fail.xml0100664000076500007650000000243307314164430015576 0ustar tjmathertjmather ]>

XML-Checker-0.13/t/insignif_ws.xml0100664000076500007650000000033707314164430017203 0ustar tjmathertjmather ]> AA BB XML-Checker-0.13/t/no_root.xml0100664000076500007650000000005207314164430016335 0ustar tjmathertjmather ]> XML-Checker-0.13/t/nodtd.xml0100664000076500007650000000012007314164430015762 0ustar tjmathertjmather This is an XML document without a DTD. A subelement XML-Checker-0.13/t/required_attr.xml0100664000076500007650000000023207314164430017530 0ustar tjmathertjmather ]> This is a test XML-Checker-0.13/t/test.xml0100664000076500007650000000005507314164430015640 0ustar tjmathertjmather XML-Checker-0.13/t/two_elem_defs.xml0100664000076500007650000000011007314164430017465 0ustar tjmathertjmather ]> XML-Checker-0.13/t/two_roots.xml0100664000076500007650000000007307314164430016720 0ustar tjmathertjmather ]> XML-Checker-0.13/t/README.txt0100664000076500007650000000044007314171276015641 0ustar tjmathertjmatherThis directory contains test cases that can be run with: make test from the parent of this directory. (Note that you must first run: make install) - chk_*.t Test cases for XML::Checker - *.xml XML files used by chk_batch.t - out/*.err Expected output for the test cases in chk_batch.t XML-Checker-0.13/t/element_text.t0100664000076500007650000000231607344404440017024 0ustar tjmathertjmather# contributed by Michel Rodriguez use strict; print "1..2\n"; use XML::Checker::Parser; $/=''; # records are now separated by an empty line # first parse, a valid document my $doc1=; my $p= new XML::Checker::Parser; eval { local $XML::Checker::FAIL= \&my_fail; $p->parse( $doc1); }; if( $@) { print "not ok 1: # $@\n"; } else { print "ok 1\n"; } # second parse, an invalid document my $doc2=; $p= new XML::Checker::Parser; eval { local $XML::Checker::FAIL= \&my_fail; $p->parse( $doc2); }; if( $@) { print "ok 2\n"; } else { print "not ok 2\n"; } # gets an error and dies after creating the error message sub my_fail { my ($code, $msg, %context)= @_; die " error $code ($msg) at line $context{line}, column $context{column}"; } __DATA__ ]> foobar ]> toto not empty foobar XML-Checker-0.13/t/empty_elt.t0100664000076500007650000000213707454404336016340 0ustar tjmathertjmather# contributed by Philippe Verdret use strict; use lib '../lib'; print "1..2\n"; use XML::Checker::Parser; $/ = ''; # records are now separated by an empty line my $Test = 0; # first parse, a valid document $Test++; my $doc1=; my $p= new XML::Checker::Parser; eval { local $XML::Checker::FAIL= \&my_fail; $p->parse( $doc1); }; if( $@) { print "not ok $Test: $@\n"; } else { print "ok $Test\n"; } # second parse, an invalid document $Test++; my $doc2 = ; $p= new XML::Checker::Parser; eval { local $XML::Checker::FAIL= \&my_fail; $p->parse( $doc2); }; if( $@) { print "ok $Test: $@\n"; } else { print "not ok $Test\n"; } # gets an error and dies after creating the error message sub my_fail { my ($code, $msg, %context)= @_; die " error $code ($msg) at line $context{line}, column $context{column}"; } __DATA__ ]> ]> XML-Checker-0.13/t/high_elt_number.t0100664000076500007650000001457107454404472017477 0ustar tjmathertjmather# contributed by Philippe Verdret use strict; use lib '../lib'; print "1..1\n"; use XML::Checker::Parser; # The X document is an invalid document my $doc= join '', ; my $p= new XML::Checker::Parser; eval { local $XML::Checker::FAIL= \&my_fail; $p->parse( $doc ); }; if( $@) { print "ok 1: $@\n"; } else { print "not ok 1\n"; } # gets an error and dies after creating the error message sub my_fail { my ($code, $msg, %context)= @_; die " error $code ($msg) at line $context{line}, column $context{column}"; } __DATA__ ]> XML-Checker-0.13/bin/0040775000076500007650000000000007444142144014451 5ustar tjmathertjmatherXML-Checker-0.13/bin/testCheckerParser.pl0100664000076500007650000000037007000464576020430 0ustar tjmathertjmatheruse XML::Checker::Parser; # Uncomment the next line to stop parsing when the first error is encountered. #local $XML::Checker::FAIL = sub { die }; my $parser = new XML::Checker::Parser (KeepCDATA => 1, NoExpand => 1); $parser->parsefile (shift); XML-Checker-0.13/bin/testCheckDOM.pl0100664000076500007650000000060707000464576017267 0ustar tjmathertjmatheruse XML::DOM; use XML::Checker; use XML::Checker::DOM; my $filename = shift; my $parser = new XML::DOM::Parser (KeepCDATA => 1, NoExpand => 1); my $dom = $parser->parsefile ($filename); print $dom->toString; # Uncomment the next line to stop checking when the first error is encountered. #local $XML::Checker::FAIL = sub { die }; my $checker = new XML::Checker; $dom->check ($checker); XML-Checker-0.13/bin/testValParser.pl0100664000076500007650000000070507000464576017610 0ustar tjmathertjmatheruse XML::DOM::ValParser; # Allow whitespace when ELEMENT rule says EMPTY $XML::Checker::Context::EMPTY::ALLOW_WHITE_SPACE = 1; my $filename = shift; # Uncomment the next line to stop parsing when the first error is encountered. #local $XML::Checker::FAIL = sub { die }; # Check while building the XML::DOM my $parser = new XML::DOM::ValParser (KeepCDATA => 1, NoExpand => 1, @ARGV); my $dom = $parser->parsefile ($filename); #print $dom->toString; XML-Checker-0.13/bin/README.txt0100664000076500007650000000127607314217424016152 0ustar tjmathertjmatherThis directory contains some sample Perl scripts. - testCheckerParser.pl Uses XML::Checker::Parser to parse the file. - testCheckDOM.pl Uses XML::DOM::Parser to build a DOM (no checking is done at parse time) and then uses XML::Checker and the check() methods in XML::DOM to check the XML::DOM::Document - filterInsignifWS.pl Uses XML::Checker to determine which whitespace is insignificant and print the filtered document to stdout. - testValParser.pl Uses XML::DOM::ValParser to create a DOM (while checking at parse time) Try the different xml files in the t/ directory to see what errors are generated. (I still need to force some of the errors in the xml sample files.) XML-Checker-0.13/README0100644000076500007650000000116007314172534014554 0ustar tjmathertjmather Perl module: XML-Checker Copyright (c) 1999,2000 Enno Derksen All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. For bug reports or suggestions send email to tjmather@tjmather.com ============= XML::Checker ===================================================== The XML::Checker Perl module contains several classes: XML::Checker - contains the XML::Checker class that is used by the others XML::Checker::Parser - an XML::Parser that validates at parse time XML::DOM::ValParser - an XML::DOM::Parser that validates at parse time