Validation avec un schéma XML en Python

104

J'ai un fichier XML et un schéma XML dans un autre fichier et je souhaite valider que mon fichier XML adhère au schéma. Comment faire cela en Python?

Je préférerais quelque chose utilisant la bibliothèque standard, mais je peux installer un package tiers si nécessaire.

Eli Courtwright
la source

Réponses:

61

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 avec lxml . La page répertorie également comment utiliser lxml pour valider avec d'autres types de schéma.

Keegan Carruthers-Smith
la source
1
lxml est du pur python ou pas? (nécessite une compilation / installation ou vous pouvez simplement l'inclure avec vos scripts python)
sorin
9
@Sorin: lxml est un wrapper au-dessus de la bibliothèque C libxml2, et n'est donc pas du pur Python.
Eli Courtwright
2
@eli Exactement ce que je voulais souligner, cela peut ne convenir à personne.
sorin
1
Les erreurs de validation ne sont pas conviviales. Comment pourrais-je procéder? mailman-mail5.webfaction.com/pipermail/lxml/2012-April/… n'aide pas.
None-da
Cette réponse est-elle toujours à jour?
Humain
27

Quant aux solutions "python pur": l'index du package répertorie:

  • pyxsd , la description dit qu'il utilise xml.etree.cElementTree, qui n'est pas "pur python" (mais inclus dans stdlib), mais le code source indique qu'il revient à xml.etree.ElementTree, donc cela compterait comme du python pur. Je ne l'ai pas utilisé, mais selon la documentation, il valide le schéma.
  • minixsv : 'un validateur de schéma XML léger écrit en Python "pur"'. Cependant, la description dit "actuellement un sous-ensemble du standard de schéma XML est pris en charge", donc cela peut ne pas être suffisant.
  • XSV , qui, je pense, est utilisé pour le validateur xsd en ligne du W3C (il semble toujours utiliser l'ancien package pyxml, qui, je pense, n'est plus maintenu)
Steven
la source
5
Je voudrais jeter un oeil à PyXB sur ceux-ci. On dirait que la plupart de ceux-ci déclarent qu'ils sont incomplets et qu'ils semblent quelque peu «morts». pyxsd dernière mise à jour en 2006, minixsv dernière mise à jour en 2008, XSV en 2007 pour autant que je sache. Ce n'est pas toujours la meilleure raison de considérer un paquet plutôt qu'un autre, mais je pense que c'est justifié dans ce cas.
oob
2
+1 pour PyXB. Je l'utilise dans Django pour valider le XML brut inséré dans la section Admin. Simple et facile à utiliser.
tatlar
21

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

Installation lxml

pip install lxml

Si vous obtenez une erreur du type "Impossible de trouver la fonction xmlCheckVersion dans la bibliothèque libxml2. Est-ce que libxml2 est installé?" , essayez de faire ceci 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 validator.py le plus 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

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 plus d'un fichier, 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

Nous pouvons maintenant 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 avec lxml

SergO
la source
14

Le package PyXB à l'adresse http://pyxb.sourceforge.net/ génère des liaisons de validation pour Python à partir de documents de schéma XML. Il gère presque toutes les constructions de schéma et prend en charge plusieurs espaces de noms.

Pabigot
la source
12

Il y a deux façons (en fait il y en a plus) que vous pouvez faire cela.
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 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

Komu
la source
J'ai 3 fichiers xsd, seulement lorsque les 3 xsd sont présents, je peux valider un xml ... est-ce que cela peut être fait avec votre méthode?
Naveen
9

Vous pouvez facilement valider un fichier XML ou une arborescence par rapport à 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 lève une exception si le fichier n'est pas validé par rapport au XSD. Cette exception contient ensuite quelques détails de violation.

Si vous souhaitez valider de nombreux fichiers, vous ne devez charger le XSD qu'une seule 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')

Alternativement, xmlschema fonctionne directement sur les objets 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))
maxschlepzig
la source