Проверка с помощью XML-схемы в Python - PullRequest
88 голосов
/ 18 ноября 2008

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

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

Ответы [ 7 ]

54 голосов
/ 18 ноября 2008

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

25 голосов
/ 06 апреля 2011

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

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

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

14 голосов
/ 22 декабря 2009

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

8 голосов
/ 26 августа 2015

Есть два способа (на самом деле их больше), которые вы можете сделать это.
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

7 голосов
/ 18 ноября 2008

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)) 
4 голосов
/ 13 сентября 2018

Вы можете легко проверить 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))
...