Tengo un archivo XML y un esquema XML en otro archivo y me gustaría validar que mi archivo XML se adhiera al esquema. ¿Cómo hago esto en Python?
Preferiría usar la biblioteca estándar, pero puedo instalar un paquete de terceros si es necesario.
Tengo un archivo XML y un esquema XML en otro archivo y me gustaría validar que mi archivo XML se adhiera al esquema. ¿Cómo hago esto en Python?
Preferiría usar la biblioteca estándar, pero puedo instalar un paquete de terceros si es necesario.
Respuestas:
Supongo que te refieres al uso de archivos XSD. Sorprendentemente, no hay muchas bibliotecas XML de Python que admitan esto. lxml sin embargo. Compruebe la validación con lxml . La página también enumera cómo usar lxml para validar con otros tipos de esquemas.
En cuanto a las soluciones de "python puro": el índice del paquete enumera:
Instalación lxml
pip install lxml
Si recibe un error como "No se pudo encontrar la función xmlCheckVersion en la biblioteca libxml2. ¿Está libxml2 instalado?" , intenta 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
Creemos el validator.py más simple
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
El paquete PyXB en http://pyxb.sourceforge.net/ genera enlaces de validación para Python a partir de documentos de esquema XML. Maneja casi todas las construcciones de esquemas y admite múltiples espacios de nombres.
Hay dos formas (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')
>> xmllint --format --pretty 1 --load-trace --debug --schema /path/to/my_schema_file.xsd /path/to/my_xml_file.xml
Puede validar fácilmente un archivo o árbol XML con un esquema XML (XSD) con el paquete xmlschema Python . 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 con el XSD. Esa excepción luego contiene algunos detalles de la infracción.
Si desea validar muchos archivos, solo tiene que cargar el XSD una vez:
xsd = xmlschema.XMLSchema('some.xsd')
for filename in filenames:
xsd.validate(filename)
Si no necesita la excepción, puede validar de esta manera:
if xsd.is_valid('doc.xml'):
print('do something useful')
Alternativamente, xmlschema trabaja 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))
lxml proporciona etree.DTD
de las pruebas en 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))