Validierung mit einem XML-Schema in Python

104

Ich habe eine XML-Datei und ein XML-Schema in einer anderen Datei und möchte überprüfen, ob meine XML-Datei dem Schema entspricht. Wie mache ich das in Python?

Ich würde etwas bevorzugen, das die Standardbibliothek verwendet, aber ich kann bei Bedarf ein Paket eines Drittanbieters installieren.

Eli Courtwright
quelle

Antworten:

61

Ich gehe davon aus, dass Sie XSD-Dateien verwenden. Überraschenderweise gibt es nicht viele Python-XML-Bibliotheken, die dies unterstützen. lxml tut es jedoch. Überprüfen Sie die Validierung mit lxml . Auf dieser Seite wird auch aufgeführt, wie lxml zur Validierung mit anderen Schematypen verwendet wird.

Keegan Carruthers-Smith
quelle
1
lxml ist reine Python oder nicht? (erfordert Kompilierung / Installation oder Sie können es einfach in Ihre Python-Skripte aufnehmen)
Sorin
9
@ Sorin: lxml ist ein Wrapper über der libxml2 C-Bibliothek und daher kein reines Python.
Eli Courtwright
2
@eli Genau das, was ich unterstreichen wollte, ist möglicherweise für niemanden geeignet.
Sorin
1
Validierungsfehler sind nicht benutzerfreundlich. Wie würde ich das machen? mailman-mail5.webfaction.com/pipermail/lxml/2012-April/… hilft nicht.
Keine-da
Ist diese Antwort noch aktuell?
Mensch
27

Was "reine Python" -Lösungen betrifft: Der Paketindex listet auf:

  • pyxsd , die Beschreibung besagt, dass xml.etree.cElementTree verwendet wird, das nicht "reines Python" ist (sondern in stdlib enthalten ist), aber der Quellcode gibt an, dass es auf xml.etree.ElementTree zurückgreift, sodass dies als reines Python gelten würde. Ich habe es nicht verwendet, aber laut den Dokumenten führt es eine Schemaüberprüfung durch.
  • minixsv : 'ein leichtgewichtiger XML-Schema-Validator, geschrieben in "reinem" Python'. In der Beschreibung heißt es jedoch, dass "derzeit eine Teilmenge des XML-Schemastandards unterstützt wird", sodass dies möglicherweise nicht ausreicht.
  • XSV , das meiner Meinung nach für den Online-xsd-Validator des W3C verwendet wird (es scheint immer noch das alte Pyxml-Paket zu verwenden, das meiner Meinung nach nicht mehr gepflegt wird).
Steven
quelle
5
Ich würde mir PyXB darüber ansehen. Sieht so aus, als wären die meisten dieser Zustände unvollständig und sie scheinen etwas "tot" zu sein. pyxsd zuletzt aktualisiert im Jahr 2006, minixsv zuletzt aktualisiert im Jahr 2008, XSV im Jahr 2007, soweit ich das beurteilen kann. Nicht immer der beste Grund, ein Paket über ein anderes zu ziehen, aber ich denke, dass dies in diesem Fall gerechtfertigt ist.
oob
2
+1 für PyXB. Ich verwende es in Django zur Validierung von Roh-XML, das im Admin-Bereich eingefügt wurde. Einfach und leicht zu bedienen.
Tatlar
21

Ein Beispiel für einen einfachen Validator in Python3 unter Verwendung der beliebten Bibliothek lxml

Installation lxml

pip install lxml

Wenn Sie eine Fehlermeldung wie "Funktion xmlCheckVersion in Bibliothek libxml2 konnte nicht gefunden werden. Ist libxml2 installiert?" Versuchen Sie dies zuerst:

# 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

Der einfachste Validator

Lassen Sie uns die einfachste validator.py erstellen

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

Schreiben Sie dann main.py und führen Sie es aus

from validator import validate

if validate("path/to/file.xml", "path/to/scheme.xsd"):
    print('Valid! :)')
else:
    print('Not valid! :(')

Ein bisschen OOP

Um mehr als eine Datei zu validieren, muss nicht jedes Mal ein XMLSchema- Objekt erstellt werden.

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

Jetzt können wir alle Dateien im Verzeichnis wie folgt validieren:

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! :(')

Weitere Optionen finden Sie hier: Validierung mit lxml

SergO
quelle
14

Das PyXB-Paket unter http://pyxb.sourceforge.net/ generiert Validierungsbindungen für Python aus XML- Schemadokumenten . Es verarbeitet fast jedes Schemakonstrukt und unterstützt mehrere Namespaces.

Pabigot
quelle
12

Es gibt zwei Möglichkeiten (tatsächlich gibt es mehr), wie Sie dies tun können.
1. mit 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. Verwenden Sie xmllint über die Befehlszeile. xmllint wird in vielen Linux-Distributionen installiert.

>> xmllint --format --pretty 1 --load-trace --debug --schema /path/to/my_schema_file.xsd /path/to/my_xml_file.xml

Komu
quelle
Ich habe 3 xsd-Dateien, nur wenn alle 3 xsd vorhanden sind, kann ich eine XML validieren ... kann dies mit Ihrer Methode durchgeführt werden?
Naveen
9

Mit dem Python-Paket xmlschema können Sie eine XML-Datei oder einen XML-Baum einfach anhand eines XML- Schemas (XSD) validieren . Es ist reines Python, verfügbar auf PyPi und hat nicht viele Abhängigkeiten.

Beispiel - Überprüfen Sie eine Datei:

import xmlschema
xmlschema.validate('doc.xml', 'some.xsd')

Die Methode löst eine Ausnahme aus, wenn die Datei nicht anhand der XSD validiert wird. Diese Ausnahme enthält dann einige Details zu Verstößen.

Wenn Sie viele Dateien validieren möchten, müssen Sie die XSD nur einmal laden:

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

Wenn Sie die Ausnahme nicht benötigen, können Sie Folgendes überprüfen:

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

Alternativ funktioniert xmlschema direkt mit Dateiobjekten und in XML-Speicherbäumen (entweder mit xml.etree.ElementTree oder lxml erstellt). Beispiel:

import xml.etree.ElementTree as ET
t = ET.parse('doc.xml')
result = xsd.is_valid(t)
print('Document is valid? {}'.format(result))
maxschlepzig
quelle