Walidacja za pomocą schematu XML w Pythonie

Mam plik XML i schemat XML w innym pliku i chciałbym sprawdzić, czy mój plik XML przylega do schematu. Jak to zrobić w Pythonie?

Wolałbym coś użyć biblioteki standardowej, ale w razie potrzeby mogę zainstalować pakiet innej firmy.

Author: jonrsharpe, 2008-11-18

7 answers

Zakładam, że masz na myśli używanie plików XSD. Co zaskakujące, nie ma wielu bibliotek XML Pythona, które to obsługują. jednak lxml. Sprawdź walidację za pomocą lxml. Strona zawiera również listę Jak używać lxml do walidacji z innymi typami schematów.

 50
Author: Keegan Carruthers-Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-11 10:18:47

Jeśli chodzi o rozwiązania "pure python": lista indeksów pakietów:

  • pyxsd , Opis mówi, że używa xml.etree.cElementTree, który nie jest "czystym Pythonem" (ale jest zawarty w stdlib), ale kod źródłowy wskazuje, że wraca do xml.etree.ElementTree, więc to się liczy jako czysty python. Nie używałem go, ale zgodnie z dokumentami, robi walidację schematu.
  • minixsv: 'lekki walidator schematu XML napisany w" czystym "Pythonie'. Jednak opis mówi "obecnie wspierany jest podzbiór standardu XML schema", więc może to nie wystarczyć.
  • XSV , który moim zdaniem jest używany do walidatora XSD W3C (nadal używa starego pakietu pyxml, który moim zdaniem nie jest już utrzymywany)
 22
Author: Steven,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-06 12:53:52

Pakiet PyXB w http://pyxb.sourceforge.net / generuje walidujące powiązania dla Pythona z dokumentów XML schema. Obsługuje prawie każdą konstrukcję schematu i obsługuje wiele przestrzeni nazw.

 13
Author: pabigot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-22 12:54:33

Przykład prostego walidatora w Python3 przy użyciu popularnej biblioteki lxml

Instalacja lxml

pip install lxml

Jeśli pojawi się błąd jak " nie można znaleźć funkcji xmlCheckVersion w bibliotece libxml2. Czy libxml2 jest zainstalowany?", spróbuj zrobić to najpierw:

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

A little bit of OOP

Aby zweryfikować więcej niż jeden plik, nie ma potrzeby tworzenia obiektu XMLSchema za każdym razem, 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! :(')

Aby uzyskać więcej opcji przeczytaj tutaj: Walidacja za pomocą lxml

 11
Author: SergO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-14 13:43:58

Są dwa sposoby (w rzeczywistości są więcej), że można to zrobić.
1. używanie 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. Użyj xmllint z linii poleceń. xmllint jest instalowany w wielu dystrybucjach Linuksa.

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

 8
Author: Komu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-26 13:51:27

Lxml dostarcza 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)) 
 7
Author: hinoglu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-22 09:45:45

Możesz łatwo zweryfikować plik XML lub drzewo na podstawie schematu XML (XSD) za pomocą Xmlschema Python package. Jest to czysty Python, dostępny na PyPi i nie ma wielu zależności.

Przykład-Walidacja pliku:

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

Metoda wyświetla wyjątek, jeśli plik nie jest poprawny względem XSD. Ten wyjątek zawiera więc pewne szczegóły naruszenia.

Jeśli chcesz zweryfikować wiele plików, musisz załadować XSD tylko raz:

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

Jeśli nie potrzebujesz wyjątku, który możesz zweryfikować w następujący sposób:

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

Alternatywnie, xmlschema działa bezpośrednio na obiektach plików i w drzewach pamięci XML (albo 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))
 0
Author: maxschlepzig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-13 09:30:12