Re: Schema validation: getting all the errors
[email protected] (Jason E. Stewart)
| Newsgroups | gmane.text.xml.xerces-p.devel |
|---|---|
| Message-ID | <[email protected]> |
"Forrest Cahoon" <[email protected]> writes: > I've been working from the xerces-c examples at > http://xml.apache.org/xerces-c/schema.html#associate but I'm having > trouble converting these to perl. Right - sorry that you're having to brave this alone - you are the first person to use Xerces-P in this direction so you are uncovering bits and pieces of the API that I haven't completely tested - and hence, some of it is broken... > $parser->setFeature("$XML::Xerces::XMLUni::fgXercesSchema", 1); > $parser->setProperty( > "XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation", > $schema); Don't you mean: $XML::Xerces::XMLUni::fgXercesSchemaExternalNoNameSpaceSchemaLocation > but that gives me the error > > Type error in argument 3 of SAX2XMLReader_setProperty. Expected _p_void at > xerces_test.pl line 15. Yes, this is a poor SWIG error, I'm afraid. This is an irritation in how Xerces-C defines the setProperty() method - the second argument in the C++ function is a void* meaning it can be any value string or integer. This shouldn't be an issue - SWIG gives me a way to map from acceptable Perl scalar value into what C++ wants. The problem is I apperently didn't handle this method properly, so it works for things that look like pointers (like integers) but not for other things (like strings). I'll have to add the proper typemap for this method and make a new snapshot. Thanks for catching this. > I've tried many variations on this theme, but nothing seems to work. > That's when I decided to try the DOM parser and was able to set the > schema with no problem (using > $parser->setExternalNoNamespaceSchemaLocation). It's my DOM parser > which dies after it hits the first error. There is a way to do this as well. I think the methods you need are: setExitOnFirstFatalError() setValidationConstraintFatal() Set these false and it *should* work... It seems to work fine on errors, but fatal errors cause lots of problems. I'm including a sample version of the validator for DOM, let me know if it helps and I'll include it in the next snapshot. Cheers, jas. -- #!/usr/bin/perl -w package MyErrorHandler; use strict; use vars qw(@ISA); @ISA = qw(XML::Xerces::PerlErrorHandler); sub warning { my $line = $_[1]->getLineNumber; my $column = $_[1]->getColumnNumber; my $message = $_[1]->getMessage; printf STDERR "%s:[%s]:%d:%d:%s:%s\n", $main::PROGRAM,$main::FILE,$line, $column, 'W', $message; } sub error { my $line = $_[1]->getLineNumber; my $column = $_[1]->getColumnNumber; my $message = $_[1]->getMessage; printf STDERR "%s:[%s]:%d:%d:%s:%s\n", $main::PROGRAM,$main::FILE,$line, $column, 'E', $message; } sub fatal_error { my $line = $_[1]->getLineNumber; my $column = $_[1]->getColumnNumber; my $message = $_[1]->getMessage; printf STDERR "%s:[%s]:%d:%d:%s:%s\n", $main::PROGRAM,$main::FILE,$line, $column, 'F', $message; } 1; package main; use strict; # use blib; use XML::Xerces; use IO::Handle; use Getopt::Long; my %OPTIONS; my $rc = GetOptions(\%OPTIONS, 'file=s', 'help', 'schema', 'validate', 'full_schema', 'namespace', ); my $USAGE = <<"EOU"; usage: $0 [required flags] required flags: --file=file_name : the XML file to parse optional parameters: --validate : enables DTD validation --namespace : enable namespace checking --schema : parse a W3C XML Schema file (forces --namespace) --full_schema : do full schema checking (forces --namespace and --schema) --help : print this message EOU die "$rc\n$USAGE" unless $rc; die $USAGE if exists $OPTIONS{help}; die "Must specify --file\n$USAGE" unless exists $OPTIONS{file}; # handle the optional command-line params my $validate = 0; my $namespace = 0; my $schema = 0; my $full_schema = 0; if (exists $OPTIONS{namespace}) { $namespace = 1; } elsif (exists $OPTIONS{schema}) { $namespace = 1; $schema = 1; } elsif (exists $OPTIONS{full_schema}) { $namespace = 1; $schema = 1; $full_schema = 1; } if (exists $OPTIONS{validate}) { $validate = 1; } # set globals used by the error handler $main::FILE = $OPTIONS{file}; $main::PROGRAM = $0; $main::PROGRAM =~ s|.*/(\w+)|$1|; my $parser = XML::Xerces::XercesDOMParser->new(); $parser->setErrorHandler(MyErrorHandler->new); # print as we parse STDERR->autoflush(); # handle the optional features eval { $parser->setDoNamespaces($namespace); $parser->setDoSchema($schema); $parser->setValidationSchemaFullChecking($full_schema); }; XML::Xerces::error($@) if $@; # and the required features eval { $parser->setValidationScheme($validate); $parser->setExitOnFirstFatalError(0); $parser->setValidationConstraintFatal(0); }; XML::Xerces::error($@) if $@; eval { my $is = XML::Xerces::LocalFileInputSource->new($OPTIONS{file}); $parser->parse($is) ; } ; XML::Xerces::error($@) if $@; exit(0);