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.

85
demandé sur jonrsharpe 2008-11-18 20:59:56

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.

50
répondu Keegan Carruthers-Smith 2013-01-11 10:18:47

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)
22
répondu Steven 2011-04-06 12:53:52

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.

13
répondu pabigot 2009-12-22 12:54:33

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

11
répondu SergO 2016-07-14 13:43:58

Il y a deux façons(en fait, il y en a plus) de le faire.
1. à l'aide de 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. 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

8
répondu Komu 2015-08-26 13:51:27

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)) 
7
répondu hinoglu 2013-05-22 09:45:45

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))
0
répondu maxschlepzig 2018-09-13 09:30:12