example - xml python 3
Validar con un esquema XML en Python (7)
Tengo un archivo XML y un esquema 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.
Si trabajas con dtd puedes disfrutar esta receta
El paquete PyXB en http://pyxb.sourceforge.net/ genera enlaces de validación para Python a partir de documentos de esquema XML. Maneja casi todos los constructos de esquema y admite múltiples espacios de nombres.
En cuanto a las soluciones de "python puro": el índice del paquete enumera:
- pyxsd , la descripción dice que usa xml.etree.cElementTree, que no es "python puro" (pero se incluye en stdlib), pero el código fuente indica que vuelve a xml.etree.ElementTree, por lo que esto contará como python puro. No lo he usado, pero de acuerdo con los documentos, sí valida el esquema.
- minixsv : ''un validador de esquema XML liviano escrito en Python'' puro ''. Sin embargo, la descripción dice que "actualmente se admite un subconjunto del estándar de esquema XML", por lo que puede no ser 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)
Supongo que te refieres al uso de archivos XSD. Sorprendentemente, no hay muchas bibliotecas XML de Python que lo respalden. lxml sin embargo. Verifica Validación con lxml . La página también enumera cómo usar lxml para validar con otros tipos de esquema.
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))
Hay dos formas (en realidad hay más) de que puedas 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'')
- Use xmllint desde la línea de comando. 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
Un ejemplo de un validador simple en Python3 usando la biblioteca popular lxml
Instalación lxml
pip install lxml
Si obtiene un error como "No se pudo encontrar la función xmlCheckVersion en la biblioteca libxml2. ¿Se instaló libxml2?" , 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 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 ver más opciones, lea aquí: Validación con lxml