Validating with an XML schema in Python

Solution 1:

I am assuming you mean using XSD files. Surprisingly there aren't many python XML libraries that support this. lxml does however. Check Validation with lxml. The page also lists how to use lxml to validate with other schema types.

Solution 2:

An example of a simple validator in Python3 using the popular library lxml

Installation lxml

pip install lxml

If you get an error like "Could not find function xmlCheckVersion in library libxml2. Is libxml2 installed?", try to do this first:

# Debian/Ubuntu
apt-get install python-dev python3-dev libxml2-dev libxslt-dev

# Fedora 23+
dnf install python-devel python3-devel libxml2-devel libxslt-devel

The simplest validator

Let's create simplest validator.py

from lxml import etree

def validate(xml_path: str, xsd_path: str) -> bool:

    xmlschema_doc = etree.parse(xsd_path)
    xmlschema = etree.XMLSchema(xmlschema_doc)

    xml_doc = etree.parse(xml_path)
    result = xmlschema.validate(xml_doc)

    return result

then write and run main.py

from validator import validate

if validate("path/to/file.xml", "path/to/scheme.xsd"):
    print('Valid! :)')
else:
    print('Not valid! :(')

A little bit of OOP

In order to validate more than one file, there is no need to create an XMLSchema object every time, therefore:

validator.py

from lxml import etree

class Validator:

    def __init__(self, xsd_path: str):
        xmlschema_doc = etree.parse(xsd_path)
        self.xmlschema = etree.XMLSchema(xmlschema_doc)

    def validate(self, xml_path: str) -> bool:
        xml_doc = etree.parse(xml_path)
        result = self.xmlschema.validate(xml_doc)

        return result

Now we can validate all files in the directory as follows:

main.py

import os
from validator import Validator

validator = Validator("path/to/scheme.xsd")

# The directory with XML files
XML_DIR = "path/to/directory"

for file_name in os.listdir(XML_DIR):
    print('{}: '.format(file_name), end='')

    file_path = '{}/{}'.format(XML_DIR, file_name)

    if validator.validate(file_path):
        print('Valid! :)')
    else:
        print('Not valid! :(')

For more options read here: Validation with lxml

Solution 3:

As for "pure python" solutions: the package index lists:

  • pyxsd, the description says it uses xml.etree.cElementTree, which is not "pure python" (but included in stdlib), but source code indicates that it falls back to xml.etree.ElementTree, so this would count as pure python. Haven't used it, but according to the docs, it does do schema validation.
  • minixsv: 'a lightweight XML schema validator written in "pure" Python'. However, the description says "currently a subset of the XML schema standard is supported", so this may not be enough.
  • XSV, which I think is used for the W3C's online xsd validator (it still seems to use the old pyxml package, which I think is no longer maintained)

Solution 4:

You can easily validate an XML file or tree against an XML Schema (XSD) with the xmlschema Python package. It's pure Python, available on PyPi and doesn't have many dependencies.

Example - validate a file:

import xmlschema
xmlschema.validate('doc.xml', 'some.xsd')

The method raises an exception if the file doesn't validate against the XSD. That exception then contains some violation details.

If you want to validate many files you only have to load the XSD once:

xsd = xmlschema.XMLSchema('some.xsd')
for filename in filenames:
    xsd.validate(filename)

If you don't need the exception you can validate like this:

if xsd.is_valid('doc.xml'):
    print('do something useful')

Alternatively, xmlschema directly works on file objects and in memory XML trees (either created with xml.etree.ElementTree or lxml). Example:

import xml.etree.ElementTree as ET
t = ET.parse('doc.xml')
result = xsd.is_valid(t)
print('Document is valid? {}'.format(result))