Validation avec un schéma XML en Python
J'ai un fichier XML et un schéma XML dans un autre fichier et je voudrais valider que mon fichier XML adhère au schéma. Comment puis-je faire cela en Python?
Je préférerais quelque chose en utilisant la bibliothèque standard, mais je peux installer un paquet tiers si nécessaire.
7 réponses
Je suppose que vous voulez dire utiliser des fichiers XSD. Étonnamment, il n'y a pas beaucoup de bibliothèques XML Python qui prennent en charge cela. lxml fait cependant. Vérifiez la Validation de avec lxml. La page répertorie également comment utiliser lxml pour valider avec d'autres types de schéma.
Comme pour les solutions "Python pur" : les listes d'index de paquets:
- pyxsd , La description indique qu'il utilise xml.programme etree.cElementTree, qui n'est pas " Python pur "( mais inclus dans stdlib), mais le code source indique qu'il revient à xml.programme etree.ElementTree, donc cela compterait comme Python pur. Je ne l'ai pas utilisé, mais selon les documents, il fait la validation du schéma.
- minixsv : 'un validateur de schéma XML léger écrit en Python "pur"'. Cependant, l' la description indique "actuellement un sous-ensemble de la norme XML schema est pris en charge", ce qui peut ne pas suffire.
- XSV , qui je pense est utilisé pour le validateur XSD en ligne du W3C (il semble toujours utiliser l'ancien paquet pyxml, qui je pense n'est plus maintenu)
Le paquet PyXB à http://pyxb.sourceforge.net / génère des liaisons de validation pour Python à partir de documents de schéma XML. Il gère presque chaque construction de schéma et prend en charge plusieurs espaces de noms.
Un exemple de validateur simple en Python3 utilisant la bibliothèque populaire lxml
Installation lxml
pip install lxml
Si vous obtenez une erreur comme "impossible de trouver la fonction xmlCheckVersion dans la bibliothèque libxml2. Libxml2 est-il installé?", essayez de le faire en premier:
# 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
Le plus simple validateur
Créons le plus 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
Ensuite, écrivez et exécutez main.py
from validator import validate
if validate("path/to/file.xml", "path/to/scheme.xsd"):
print('Valid! :)')
else:
print('Not valid! :(')
Un peu de POO
Pour valider plus d'un fichier, il n'est pas nécessaire de créer un objet XMLSchema à chaque fois, donc:
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
Maintenant, nous pouvons valider tous les fichiers dans le répertoire comme suit:
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! :(')
Pour plus d'options de lire ici: Validation avec lxml
Il y a deux façons(en fait, il y en a plus) de le faire.
1. à l'aide de lxmlpip 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')
- utilisez xmllint depuis la ligne de commande. xmllint est installé dans de nombreuses distributions linux.
>> xmllint --format --pretty 1 --load-trace --debug --schema /path/to/my_schema_file.xsd /path/to/my_xml_file.xml
Lxml fournit etree.DTD
À Partir des essais sur 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))
Vous pouvez facilement valider un fichier XML ou une arborescence par rapport à un schéma XML (XSD) avec le paquet python xmlschema . C'est Python pur, disponible sur PyPi et n'a pas beaucoup de dépendances.
Exemple - valider un fichier:
import xmlschema
xmlschema.validate('doc.xml', 'some.xsd')
La méthode déclenche une exception si le fichier ne se valide pas par rapport au XSD. Cette exception contient alors des détails de violation.
Si vous voulez valider de nombreux fichiers, vous n'avez qu'à charger le XSD une seule fois:
xsd = xmlschema.XMLSchema('some.xsd')
for filename in filenames:
xsd.validate(filename)
Si vous n'avez pas besoin de l'exception que vous pouvez valider comme ceci:
if xsd.is_valid('doc.xml'):
print('do something useful')
Alternativement, xmlschema fonctionne directement sur les objets de fichier et dans les arbres XML en mémoire (soit créés avec xml.programme etree.ElementTree ou lxml). Exemple:
import xml.etree.ElementTree as ET
t = ET.parse('doc.xml')
result = xsd.is_valid(t)
print('Document is valid? {}'.format(result))