Проверка с помощью XML-схемы в Python


У меня есть XML-файл и XML-схема в другом файле, и я хотел бы проверить, что мой XML-файл придерживается схемы. Как это сделать в Python?

Я бы предпочел что-то использовать стандартную библиотеку, но я могу установить сторонний пакет, если это необходимо.

7 85

7 ответов:

Я предполагаю, что вы имеете в виду использование XSD-файлов. Удивительно, но не так много библиотек python XML, которые поддерживают это. однако lxml делает это. Проверьте проверка с помощью lxml. На этой странице также указано, как использовать этот пакет содержит файлы для проверки с другими типами схем.

Что касается решений "pure python": списки индексов пакетов:

  • pyxsd, описание говорит, что он использует xml.etree.cElementTree, который не является "чистым python" (но включен в stdlib), но исходный код указывает, что он возвращается к xml.etree.ElementTree, так что это будет считаться чистым питоном. Не использовал его, но согласно документам, он выполняет проверку схемы.
  • minixsv: 'облегченный валидатор схемы XML написанный внутри "чистый" питон. Однако в описании говорится: "в настоящее время поддерживается подмножество стандарта схемы XML", поэтому этого может быть недостаточно.
  • XSV, который, я думаю, используется для онлайн-валидатора xsd W3C (он по-прежнему использует старый пакет pyxml, который, я думаю, больше не поддерживается)

пакет PyXB в http://pyxb.sourceforge.net/ создает проверяющие привязки для Python из документов XML-схемы. Он обрабатывает почти каждую конструкцию схемы и поддерживает несколько пространств имен.

пример простого валидатора в Python3 с использованием популярной библиотеки lxml

установка lxml

pip install lxml

если вы получаете сообщение об ошибке, как " не удалось найти функцию xmlCheckVersion в библиотеке libxml2. Установлен библиотеке libxml2?" попробуйте сделать это первой:

# 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

самый простой валидатор

давайте создадим самый простой 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

затем напишите и запустите main.py

from validator import validate

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

немного ООП

для проверки нескольких файлов нет необходимости создавать XMLSchema

есть два способа(на самом деле их больше), что вы могли бы сделать это.
1. используя 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. использовать xmllint из командной строки. xmllint устанавливается во многих дистрибутивах linux.

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

lxml обеспечивает etree.DTD

из тестов на 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)) 

вы можете легко проверить XML-файл или дерево по схеме XML (XSD) с помощью Xmlschema Python package. Это чистый питон, доступный на PyPi и не имеет много зависимостей.

пример - проверка файла:

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

метод вызывает исключение, если файл не проверяется на XSD. Это исключение затем содержит некоторые детали нарушения.

если вы хотите проверить много файлов, которые вы только должны загрузить XSD один раз:

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

Если вам не нужно исключение, вы можете проверить следующим образом:

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

кроме того, xmlschema напрямую работает с файловыми объектами и XML-деревьями памяти (либо созданными с помощью xml.etree.ElementTree или lxml). Пример:

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