Schema Validators

Schema and Schematron Validators

Each schema language checks different things, so pick the validator for the language your contract uses, and know what it cannot see. The same feed with a negative price, through every validator on this machine:

validators.sh: one bad feed, five validatorsShell
# One feed, every validator on this machine; bad.xml has a negative price
sed 's/>39.50</>-39.50</' booknest-catalog.xml > bad.xml
sed '1a <!DOCTYPE catalog SYSTEM "booknest.dtd">' bad.xml > bad-dtd.xml
v() { printf '%-22s ' "$1"; shift; "$@" > /dev/null 2>&1 && echo valid || echo INVALID; }
v "xmllint, DTD" xmllint --noout --valid bad-dtd.xml
v "xmllint, XSD 1.0" xmllint --noout --schema catalog.xsd bad.xml
v "Jing, RELAX NG" jing booknest.rng bad.xml
v "xmlschema, XSD 1.1" ~/de-venv/bin/xmlschema-validate --version 1.1 \
  --schema catalog11.xsd bad.xml
xslt3 -xsl:$HOME/xml-tools/schxslt2/schxslt2-1.11.2/transpile.xsl -s:booknest.sch -o:sch.xsl
v "SchXslt2, Schematron" sh -c '! xslt3 -xsl:sch.xsl -s:bad.xml | grep -q failed-assert'
Output
xmllint, DTD           valid
xmllint, XSD 1.0       INVALID
Jing, RELAX NG         INVALID
xmlschema, XSD 1.1     INVALID
SchXslt2, Schematron   valid

The DTD types the price as text, and the Schematron rules of Schematron test record counts and dates, not prices, so both passed the bad value; XSD 1.0, RELAX NG and XSD 1.1 caught it. Layer them: a grammar (XSD or RELAX NG) for structure and types, Schematron for business rules. Open-source choices: xmllint 3,427 and lxml 3,063 (DTD, XSD 1.0, RELAX NG), Jing 258 (RELAX NG), xmlschema 476 (XSD 1.1), Xerces-J (XSD 1.1), SchXslt2 on Saxon-HE 726,956 (Schematron); Saxon-EE validates XSD 1.1 commercially.