libxml2 doesn't correctly raise errors on Occurence based restrictions
I came across this error when validating XML files against an XSD in Nokogiri, which uses libxml2 under the hood.
When validating a complexType XML element, if a node fails validation due to an Occurence restriction, and it is the last node in the complex element, the validation error will not raise, and will pass as a valid document. If there is another node in the sequence that is allowed, then at that point the document will fail validation. However, the error that is thrown is misleading, because it will say that the second element is the one that is out of place, rather than the one that is actually out of place.
The easiest way to reproduce this is with xmllint:
xmllint --noout --schema example_xsd.xsd incorrectly_passing.xml
incorrectly_passing.xml validates
xmllint --noout --schema example_xsd.xsd failing_wrong_error.xml
failing_wrong_error.xml:4: element Wheel: Schemas validity error : Element '{http://foo.bar/example}Wheel': This element is not expected.
failing_wrong_error.xml fails to validate
Tested on mac:
xmllint --version
xmllint: using libxml version 20904
compiled with: Threads Tree Output Push Reader Patterns Writer SAXv1 FTP HTTP DTDValid HTML Legacy C14N Catalog XPath XPointer XInclude ICU ISO8859X Unicode Regexps Automata Expr Schemas Schematron Modules Debug Zlib
Tested on RHEL 6.8:
xmllint --version
xmllint: using libxml version 20706
compiled with: Threads Tree Output Push Reader Patterns Writer SAXv1 FTP HTTP DTDValid HTML Legacy C14N Catalog XPath XPointer XInclude Iconv ISO8859X Unicode Regexps Automata Expr Schemas Schematron Modules Debug Zlib
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema elementFormDefault="qualified" targetNamespace="http://foo.bar/example" xmlns:example="http://foo.bar/example" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Car">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Wing" type="xsd:string" minOccurs="0" maxOccurs="0"/>
<xsd:element name="Wheel" type="xsd:string" minOccurs="0" maxOccurs="4"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<?xml version="1.0" encoding="UTF-8"?>
<example:Car xmlns:example="http://foo.bar/example">
<!-- This should not pass, min/max Wings is set to 0 -->
<example:Wing>This doesn't go here</example:Wing>
</example:Car>
<?xml version="1.0" encoding="UTF-8"?>
<example:Car xmlns:example="http://foo.bar/example">
<!-- This should not pass, min/max Wings is set to 0 -->
<example:Wing>This doesn't go here</example:Wing>
<!-- The error libxml gives actually says the Wheel -->
<!-- element is not expected, even though it is min 0 -->
<!-- max 4, as defined in the XSD -->
<example:Wheel>This is fine</example:Wheel>
</example:Car>