web-dev-qa-db-fra.com

Validation avec un schéma XML dans 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 faire cela en Python?

Je préférerais utiliser la bibliothèque standard, mais je peux installer un paquet tiers si nécessaire.

92
Eli Courtwright

Je suppose que vous voulez dire en utilisant des fichiers XSD. Étonnamment, il n’ya pas beaucoup de python bibliothèques XML qui supportent cela. Lxml le fait cependant. Check Validation avec lxml . La page explique également comment utiliser lxml pour valider avec d’autres types de schéma.

55

En ce qui concerne les solutions "python pur": l'index des packages répertorie:

  • pyxsd , la description indique qu'elle utilise xml.etree.cElementTree, qui n'est pas "pur python" (mais incluse dans stdlib), mais que le code source indique qu'il est redirigé vers xml.etree.ElementTree, donc cela compterait comme du python pur. Je ne l'ai pas utilisé, mais selon la documentation, il effectue la validation de schéma.
  • minixsv : 'un validateur de schéma XML léger écrit en Python "pur". Cependant, la description indique "actuellement, un sous-ensemble de la norme de schéma XML est pris en charge", ce qui risque de ne pas être suffisant.
  • XSV , qui est, je pense, utilisé pour le validateur en ligne xsd du W3C (il semble toujours utiliser l'ancien paquet pyxml, qui n'est plus maintenu, à mon avis)
25
Steven

Exemple de validateur simple en Python3 utilisant la bibliothèque populaire lxml

Installation lxml

pip install lxml

Si vous obtenez une erreur du genre "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 validateur le plus simple

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

puis é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

Afin de valider plusieurs fichiers, il n'est pas nécessaire de créer un objet XMLSchema à chaque fois. Par conséquent:

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 du 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, lisez ici: Validation with lxml

18
SergO

Le package PyXB sur 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. .

14
pabigot

Vous pouvez le faire de deux manières (en fait, il y en a plus).
1. en utilisant 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 à partir de 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
Komu

lxml fournit etree.DTD

à partir des tests 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
altunyurt

Vous pouvez facilement valider un fichier XML ou une arborescence XML contre un schéma XML (XSD) avec le package xmlschema Python) . C'est du pur Python, 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 n'est pas validé par rapport à XSD. Cette exception contient alors certains détails de violation.

Si vous souhaitez valider de nombreux fichiers, il vous suffit de charger le fichier XSD une fois:

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

Si vous n'avez pas besoin de l'exception, vous pouvez valider comme ceci:

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

Sinon, xmlschema fonctionne directement sur les objets de fichier et dans les arborescences XML en mémoire (créées avec xml.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))
5
maxschlepzig