Validating with an XSD

Validating BookNest's Catalog Against an XSD

A pipeline's validation gate should report every error and quarantine the file. xmlschema 476 's iter_errors() yields every error with its path. Here a partner feed arrives with five mistakes: a bad ISBN check digit, a short SKU, a duplicate SKU, a 5.5 rating and a negative price:

validate.py: reporting every XSD 1.1 error in a clean and a broken feedPython
~/de-venv/bin/pip install --quiet xmlschema==4.3.2      # into the venv of Section 1.11.2
sed -e 's#<identifier type="sku">BN-0001#<identifier type="isbn13">9781234567890#' \
    -e 's#>BN-0002<#>BN-12<#' -e 's#>BN-0005<#>BN-0004<#' \
    -e 's#<price currency="USD">18.75#<price currency="USD">-18.75#' \
    -e 's#<rating>4.1#<rating>5.5#' booknest-catalog.xml > bad-feed.xml
cat > validate.py <<'EOF'
import sys
import xmlschema
schema = xmlschema.XMLSchema11("catalog11.xsd")      # XSD 1.1: assertions, alternatives
for path in sys.argv[1:]:
    errors = list(schema.iter_errors(path))
    print(f"{path}: {len(errors)} error(s)")
    for e in errors:
        print(f"  {e.path}: {e.reason}")
EOF
~/de-venv/bin/python validate.py booknest-catalog.xml bad-feed.xml
Output
booknest-catalog.xml: 0 error(s)
bad-feed.xml: 5 error(s)
  /catalog/book[1]/identifier: assertion test is false
  /catalog/book[2]/identifier: value doesn't match any pattern of ['BN-\\d{4}']
  /catalog/book[4]/rating: value has to be less than or equal than Decimal('5')
  /catalog/book[4]/supply/price: value has to be greater than Decimal('0')
  /catalog/book[5]/identifier: duplicated value ('BN-0004',) for Xsd11Unique(name='uniqueSku')

One run lists every error. xmllint 3,427 with the 1.0 catalog.xsd reports only the rating, price and duplicate. schema.to_dict(path) decodes a valid feed into typed values (Decimal prices) ready to load as rows.