webentwicklung-frage-antwort-db.com.de

Validierung mit einem XML-Schema in Python

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 vorziehen, das die Standardbibliothek verwendet, aber ich kann bei Bedarf ein Paket eines Drittanbieters installieren.

92
Eli Courtwright

Ich gehe davon aus, dass Sie XSD-Dateien verwenden wollen. Überraschenderweise gibt es nicht viele python XML-Bibliotheken, die dies unterstützen. Lxml funktioniert jedoch. Check Validierung mit lxml . Die Seite listet auch auf, wie man lxml zur Validierung mit anderen verwendet Schematypen.

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

  • pyxsd , die Beschreibung besagt, dass xml.etree.cElementTree verwendet wird, was nicht "reines Python" ist (sondern in stdlib enthalten ist), aber der Quellcode zeigt an, dass es auf xml.etree.ElementTree zurückfällt Dies würde als reine Python zählen. Habe es noch nicht benutzt, aber laut Dokumentation führt es eine Schemaüberprüfung durch.
  • minixsv : 'Ein einfacher 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 W3C-Online-XSD-Validator verwendet wird (es scheint immer noch das alte Pyxml-Paket zu verwenden, das meiner Meinung nach nicht mehr gewartet wird)
25
Steven

Ein Beispiel für einen einfachen Validator in Python3, der die beliebte Bibliothek lxml verwendet

Installation lxml

pip install lxml

Wenn Sie eine Fehlermeldung wie "Die Funktion xmlCheckVersion konnte nicht in der Bibliothek libxml2 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

Erstellen wir die einfachste 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

dann schreibe und starte main.py

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. Deshalb:

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

18
SergO

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

14
pabigot

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 in der Befehlszeile. xmllint ist 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

8
Komu

lxml liefert etree.DTD

von den Tests auf 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

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

Beispiel - Datei validieren:

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

Die Methode löst eine Ausnahme aus, wenn die Datei nicht gegen die 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 folgendermaßen validieren:

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

Alternativ arbeitet xmlschema direkt mit Dateiobjekten und in Speicher-XML-Bä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))
5
maxschlepzig