Validación con un esquema XML en Python


Tengo un archivo XML y esquemas XML en otro archivo y me gustaría validar que mi archivo XML se adhiere al esquema. ¿Cómo hago esto en Python?

Preferiría algo usando la biblioteca estándar, pero puedo instalar un paquete de terceros si es necesario.

Author: jonrsharpe, 2008-11-18

7 answers

Asumo que se refiere al uso de archivos XSD. Sorprendentemente, no hay muchas bibliotecas XML de python que soporten esto. lxml lo hace sin embargo. Compruebe Validación con lxml. La página también muestra cómo usar lxml para validar con otros tipos de esquema.

 50
Author: Keegan Carruthers-Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-11 10:18:47

En cuanto a las soluciones "pure python" : las listas de índice de paquetes:

  • pyxsd , la descripción dice que usa xml.etree.cElementTree, que no es "python puro" (pero está incluido en stdlib), pero el código fuente indica que vuelve a xml.etree.ElementTree, así que esto contaría como python puro. No lo he usado, pero de acuerdo con los documentos, hace validación de esquema.
  • minixsv: 'un validador de esquema XML ligero escrito en Python "puro"'. Sin embargo, el la descripción dice "actualmente se admite un subconjunto del estándar XML schema", por lo que puede que esto no sea suficiente.
  • XSV , que creo que se usa para el validador xsd en línea del W3C (todavía parece usar el viejo paquete pyxml, que creo que ya no se mantiene)
 22
Author: Steven,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-06 12:53:52

El paquete PyXB en http://pyxb.sourceforge.net / genera enlaces de validación para Python a partir de documentos XML schema. Maneja casi todas las construcciones de esquema y admite varios espacios de nombres.

 13
Author: pabigot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-12-22 12:54:33

Un ejemplo de un validador simple en Python3 usando la popular biblioteca lxml

Instalación lxml

pip install lxml

Si obtiene un error como "No se pudo encontrar la función xmlCheckVersion en la biblioteca libxml2. ¿Está instalado libxml2?", trata de hacer esto primero:

# 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

El validador más simple

Vamos a crear el más simple 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

Luego escribe y ejecuta main.py

from validator import validate

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

Un poco de OOP

Para validar más de un archivo, no es necesario crear un objeto XMLSchema cada vez, por lo tanto:

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

Ahora podemos validar todos los archivos en el directorio de la siguiente manera:

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! :(')

Para más opciones lea aquí: Validación con lxml

 11
Author: SergO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-14 13:43:58

Hay dos maneras(en realidad hay más) de hacer esto.
1. usando lxml
pip install lxml

from lxml import etree, objectify
from lxml.etree import XMLSyntaxError

def xml_validator(some_xml_string, xsd_file='/path/to/my_schema_file.xsd'):
    try:
        schema = etree.XMLSchema(file=xsd_file)
        parser = objectify.makeparser(schema=schema)
        objectify.fromstring(some_xml_string, parser)
        print "YEAH!, my xml file has validated"
    except XMLSyntaxError:
        #handle exception here
        print "Oh NO!, my xml file does not validate"
        pass

xml_file = open('my_xml_file.xml', 'r')
xml_string = xml_file.read()
xml_file.close()

xml_validator(xml_string, '/path/to/my_schema_file.xsd')
  1. Use xmllint desde la línea de comandos. xmllint viene instalado en muchas distribuciones de linux.

>> xmllint --format --pretty 1 --load-trace --debug --schema /path/to/my_schema_file.xsd /path/to/my_xml_file.xml

 8
Author: Komu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-26 13:51:27

Lxml proporciona etree.DTD

De las pruebas de http://lxml.de/api/lxml.tests.test_dtd-pysrc.html

...
root = etree.XML(_bytes("<b/>")) 
dtd = etree.DTD(BytesIO("<!ELEMENT b EMPTY>")) 
self.assert_(dtd.validate(root)) 
 7
Author: hinoglu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-22 09:45:45

Puede validar fácilmente un archivo o árbol XML contra un esquema XML (XSD) con el paquete python xmlschema. Es Python puro, disponible en PyPI y no tiene muchas dependencias.

Ejemplo-validar un archivo:

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

El método genera una excepción si el archivo no se valida contra el XSD. Esa excepción contiene algunos detalles de violación.

Si quieres validar muchos archivos solo tienes que cargar el XSD una vez:

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

Si no necesita la excepción que puede validar de esta manera:

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

Alternativamente, xmlschema funciona directamente en objetos de archivo y en árboles XML de memoria (ya sea creados con xml.etree.ElementTree o lxml). Ejemplo:

import xml.etree.ElementTree as ET
t = ET.parse('doc.xml')
result = xsd.is_valid(t)
print('Document is valid? {}'.format(result))
 0
Author: maxschlepzig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-13 09:30:12