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

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

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


person Eli Courtwright    schedule 18.11.2008    source источник


Ответы (7)


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

person Keegan Carruthers-Smith    schedule 18.11.2008
comment
lxml - чистый питон или нет? (требует компиляции / установки или вы можете просто включить его в свои скрипты на Python) - person sorin; 14.06.2010
comment
@Sorin: lxml - это оболочка над библиотекой libxml2 C и, следовательно, не чистый Python. - person Eli Courtwright; 07.07.2010
comment
@eli Именно то, что я хотел подчеркнуть, это может никому не подойти. - person sorin; 08.07.2010
comment
Ошибки проверки не удобны для пользователя. Как мне это сделать? mailman-mail5.webfaction.com/pipermail/lxml/2012- Апрель / не помогает. - person None-da; 24.05.2012
comment
Этот ответ все еще актуален? - person Human; 22.04.2020
comment
Да, вы все еще можете использовать lxml. С тех пор кажется, что был создан pypi.org/project/xmlschema, который выглядит как хорошая альтернатива на чистом питоне. (Сам не пользовался). - person Keegan Carruthers-Smith; 23.04.2020

Пример простого валидатора на 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, поэтому:

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

Теперь мы можем проверить все файлы в каталоге следующим образом:

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

Дополнительные параметры см. Здесь: Проверка с помощью lxml

person SergO    schedule 22.06.2016

Что касается решений "на чистом питоне": в индексе пакетов перечислены:

  • pyxsd, в описании говорится, что он использует xml.etree.cElementTree, который не является «чистым питоном» (но включен в stdlib) , но исходный код указывает, что он возвращается к xml.etree.ElementTree, поэтому это будет считаться чистым питоном. Не использовал его, но, согласно документации, он выполняет проверку схемы.
  • minixsv: «облегченный валидатор схемы XML, написанный на« чистом »Python». Однако в описании говорится, что «в настоящее время поддерживается подмножество стандарта схемы XML», поэтому этого может быть недостаточно.
  • XSV, который, я думаю, используется для онлайн-валидатора xsd W3C (кажется, он все еще использует старый пакет pyxml, который я думаю уже не поддерживается)
person Steven    schedule 06.04.2011
comment
Я бы посмотрел на PyXB поверх них. Похоже, что в большинстве из них они неполны и кажутся несколько мертвыми. Насколько я могу судить, pyxsd последний раз обновлялся в 2006 году, minixsv последний раз обновлялся в 2008 году, XSV - в 2007 году. Не всегда лучший повод отдавать предпочтение одному пакету, но я думаю, что в данном случае он оправдан. - person oob; 31.12.2011
comment
+1 для PyXB. Я использую его в Django для проверки необработанного XML, вставленного в раздел администратора. Легко и просто использовать. - person tatlar; 04.04.2013

Вы можете легко проверить XML-файл или дерево на соответствие XML-схеме (XSD) с помощью пакета xmlschema Python. Это чистый Python, доступный на 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))
person maxschlepzig    schedule 13.09.2018

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

person pabigot    schedule 22.12.2009

Это можно сделать двумя способами (на самом деле их больше).
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

person Komu    schedule 26.08.2015
comment
У меня есть 3 файла xsd, только когда присутствуют все 3 файла xsd, я могу проверить xml ... можно ли это сделать с помощью вашего метода? - person Naveen; 24.01.2019

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)) 
person altunyurt    schedule 18.11.2008