Re: Validating with XML::LibXML::RelaxNG?

Petr Pajas <[email protected]>
Newsgroups gmane.comp.lang.perl.xml
Message-ID <[email protected]>
Hi Ken

I just looked into the libxml2 source code to find out that it stores
some per-node psvi information based on previous successful
validation. If the node->psvi pointer equals the pointer to the
definition it is currently being tested against, the validation of
that node is skipped. This means that nodes that were once valid
remain valid. By looking at the code I'm rather convinced this is
considered a feature, not a bug.

Not sure how to deal with this in XML::LibXML. Options include:

- clear psvi on every change of the tree (ugly, since this involves
too many lines)
- traverse the tree and clear psvi before each validation (safe, but
probably redundant for freshly parsed documents)
- expose an API to clear psvi before validation

Which would you prefer/suggest (Ken, list, ...)?

-- Petr

2009/7/5 Rodent of Unusual Size <[email protected]>:
> I'm getting seemingly anomalous results when using
> XML::LibXML::RelaxNG to validate documents.
>
> Firstly, is an instance supposed to be reusable?  Can
> it be used to validate multiple RNG documents in sequence?
> Or do I need to instantiate a new object for each document
> I want to validate?  Empirical evidence suggests the former,
> but it doesn't appear to be clearly spelt out in the docco.
>
> Next: I'm using XML::LibXML::RelaxNG to verify a schema --
> sort of working in both directions, as it were.  I build a
> document incrementally and validate it at each stage to make
> sure that a) I'm not messing up the structure of the document
> as I build it, and b) that the RNG schema agrees with me about
> what's valid.  Included in the testing are intentional errors
> to make sure the schema catches them, too.
>
> If I take this incremental document and export it to XML with
> its toString() method, create a new document from it with
> XML::LibXML->new(string => $foo), and pass the result to
> $rng->validate(), it *always* behaves as expected.  If I pass
> it the XML::LibXML::Document object I've been frobbing, it
> sometimes says the invalid XML is, in fact, valid.
>
> I'm frobbing the document with addChild() and removeChild(), using
> element objects I created at the beginning with createElement().
> In other words, the same nodes are getting moved around:
> inserted here, removed and re-inserted over there, etc.
>
> The document's toString() output shows the correct XML.  Is
> what I'm doing with shuffling nodes not supported at some
> level?  Are there artifacts of the shuffling that are getting
> left behind and confusing the RNG validator when it scans
> the DOM document?
>
> I've got a test case that illustrates the behaviour.
> I'm attaching the schema in RNC and RNG format, the Perl
> demonstrating the behaviour, and the output from the
> script.  I basically build the document by hand and run it
> through the validator four times.  For each run, the output
> contains the XML (from the document's toString() method),
> the results of eval'ing validation on the document-as-modified,
> and the results from validating a new document created from
> the XML.
>
> The last case shows that validation of the bad XML fails
> as expected, but does *not* fail on the document from which
> the XML was extracted.
>
> Am I misusing the document manipulation mechanisms?  Or should
> this work and I've found a bug?  Or what?
>
> Thanks!
> --
> #ken    P-)}
>
> Ken Coar, Sanagendamgagwedweinini  http://Ken.Coar.Org/
> Author, developer, opinionist      http://Apache-Server.Com/
>
> "Millennium hand and shrimp!"
>
> namespace rng = "http://relaxng.org/ns/structure/1.0"
> datatypes xsd = "http://www.w3.org/2001/XMLSchema-datatypes"
>
> #
> # The master container.
> #
> start =
>    element root
>        {
>            attribute.name,
>            element.onedown?
>        }
>
> attribute.name = attribute name
>    {
>        text
>    }
>
> element.onedown = element onedown
>    {
>        attribute.name?,
>        element.twodown*
>    }
>
> element.twodown = element twodown
>    {
>        attribute.name
>    }
>
>
> #! /usr/bin/perl -w
>
> use strict;
> use warnings;
> use Test::More;
>
> use Carp;
> use Data::Dumper;
> use File::Spec;
>
> use XML::LibXML;
>
> my $parser = XML::LibXML->new();
> my $rng = XML::LibXML::RelaxNG->new(location => 'demo.rng');
>
> my $seed_xml = <<'EOXML';
> <?xml version="1.0" encoding="UTF-8"?>
> <root/>
> EOXML
>
> my $doc = $parser->parse_string($seed_xml);
> my $xpath = XML::LibXML::XPathContext->new($doc);
> my ($rootElem) = $xpath->findnodes('//root', $doc);
>
> my $bogusElem = $doc->createElement('bogus-element');
> my $onedownElem = $doc->createElement('onedown');
> my $twodownElem = $doc->createElement('twodown');
>
> my $xml;
> my @results;
> my $result;
>
> #
> # Should fail; the root element needs a 'name' attribute.
> #
> $@ = undef;
> $xml = $doc->toString(2);
> eval('$rng->validate($doc);');
> $result = $@;
> eval('$rng->validate($parser->parse_string($xml));');
> push(@results, { xml => "\n$xml", raw => "$@", DOM => "$result"});
>
> #
> # Should succeed; the root element is now complete.
> #
> $rootElem->setAttribute('name', 'rootElem');
> $@ = undef;
> $xml = $doc->toString(2);
> eval('$rng->validate($doc);');
> $result = $@;
> eval('$rng->validate($parser->parse_string($xml));');
> push(@results, { xml => "\n$xml", raw => "$@", DOM => "$result"});
>
> #
> # Should succeed; the root element now has a vali child.
> #
> $rootElem->addChild($onedownElem);
> $@ = undef;
> $xml = $doc->toString(2);
> eval('$rng->validate($doc);');
> $result = $@;
> eval('$rng->validate($parser->parse_string($xml));');
> push(@results, { xml => "\n$xml", raw => "$@", DOM => "$result"});
>
> #
> # Should fail; the root element can't have <twodown/> as a child.
> #
> $rootElem->addChild($twodownElem);
> $@ = undef;
> $xml = $doc->toString(2);
> eval('$rng->validate($doc);');
> $result = $@;
> eval('$rng->validate($parser->parse_string($xml));');
> push(@results, { xml => "\n$xml", raw => "$@", DOM => "$result"});
>
> print Dumper(\@results);
> #
> # Local Variables:
> # mode: cperl
> # tab-width: 4
> # indent-tabs-mode: nil
> # End:
> #
>
> $VAR1 = [
>          {
>            'xml' => '
> <?xml version="1.0" encoding="UTF-8"?>
> <root/>
> ',
>            'DOM' => 'unknown-9da80b0:0: Relax-NG validity error : Element root failed to validate attributes
> ',
>            'raw' => 'unknown-a0154f0:0: Relax-NG validity error : Element root failed to validate attributes
> '
>          },
>          {
>            'xml' => '
> <?xml version="1.0" encoding="UTF-8"?>
> <root name="rootElem"/>
> ',
>            'DOM' => '',
>            'raw' => ''
>          },
>          {
>            'xml' => '
> <?xml version="1.0" encoding="UTF-8"?>
> <root name="rootElem">
>  <onedown/>
> </root>
> ',
>            'DOM' => '',
>            'raw' => ''
>          },
>          {
>            'xml' => '
> <?xml version="1.0" encoding="UTF-8"?>
> <root name="rootElem">
>  <onedown/>
>  <twodown/>
> </root>
> ',
>            'DOM' => '',
>            'raw' => 'unknown-a014ff8:0: Relax-NG validity error : Did not expect element twodown there
> '
>          }
>        ];
>
> _______________________________________________
> Perl-XML mailing list
> [email protected]
> To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
>
>
_______________________________________________
Perl-XML mailing list
[email protected]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.