Mam plik XML i schemat XML w innym pliku i chciałbym sprawdzić, czy mój plik XML jest zgodny ze schematem. Jak to zrobić w Pythonie?
Wolałbym coś przy użyciu biblioteki standardowej, ale w razie potrzeby mogę zainstalować pakiet innej firmy.
Mam plik XML i schemat XML w innym pliku i chciałbym sprawdzić, czy mój plik XML jest zgodny ze schematem. Jak to zrobić w Pythonie?
Wolałbym coś przy użyciu biblioteki standardowej, ale w razie potrzeby mogę zainstalować pakiet innej firmy.
Odpowiedzi:
Zakładam, że masz na myśli używanie plików XSD. Zaskakujące jest, że nie ma wielu bibliotek Pythona XML, które to obsługują. lxml jednak. Sprawdź walidację za pomocą lxml . Strona zawiera również listę sposobów używania lxml do sprawdzania poprawności z innymi typami schematów.
Jeśli chodzi o rozwiązania „czystego Pythona”: indeks pakietów zawiera:
Instalacja lxml
pip install lxml
Jeśli pojawi się błąd typu „Nie można znaleźć funkcji xmlCheckVersion w bibliotece libxml2. Czy zainstalowano bibliotekę libxml2?” , spróbuj najpierw to zrobić:
# 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
Najprostszy walidator
Stwórzmy najprostszy 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
następnie napisz i uruchom main.py
from validator import validate
if validate("path/to/file.xml", "path/to/scheme.xsd"):
print('Valid! :)')
else:
print('Not valid! :(')
Trochę OOP
Aby zweryfikować więcej niż jeden plik, nie ma potrzeby tworzenia za każdym razem obiektu XMLSchema , dlatego:
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
Teraz możemy zweryfikować wszystkie pliki w katalogu w następujący sposób:
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! :(')
Więcej opcji znajdziesz tutaj: Walidacja za pomocą lxml
Pakiet PyXB pod adresem http://pyxb.sourceforge.net/ generuje weryfikację powiązań dla Pythona z dokumentów schematu XML. Obsługuje prawie każdą konstrukcję schematu i obsługuje wiele przestrzeni nazw.
Można to zrobić na dwa sposoby (a właściwie jest ich więcej).
1. używając 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')
>> xmllint --format --pretty 1 --load-trace --debug --schema /path/to/my_schema_file.xsd /path/to/my_xml_file.xml
Możesz łatwo sprawdzić poprawność pliku XML lub drzewa w oparciu o schemat XML (XSD) za pomocą pakietu xmlschema Python . To czysty Python, dostępny na PyPi i nie ma wielu zależności.
Przykład - sprawdź poprawność pliku:
import xmlschema
xmlschema.validate('doc.xml', 'some.xsd')
Metoda zgłasza wyjątek, jeśli plik nie jest sprawdzany pod kątem XSD. Ten wyjątek zawiera następnie szczegóły dotyczące naruszenia.
Jeśli chcesz zweryfikować wiele plików, wystarczy załadować plik XSD tylko raz:
xsd = xmlschema.XMLSchema('some.xsd')
for filename in filenames:
xsd.validate(filename)
Jeśli nie potrzebujesz wyjątku, możesz zweryfikować w ten sposób:
if xsd.is_valid('doc.xml'):
print('do something useful')
Alternatywnie xmlschema działa bezpośrednio na obiektach plików i drzewach XML pamięci (utworzonych za pomocą xml.etree.ElementTree lub lxml). Przykład:
import xml.etree.ElementTree as ET
t = ET.parse('doc.xml')
result = xsd.is_valid(t)
print('Document is valid? {}'.format(result))
lxml udostępnia etree.DTD
z testów na 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))