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

104

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

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

Эли Кортрайт
источник

Ответы:

61

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

Киган Каррутерс-Смит
источник
1
lxml - чистый питон или нет? (требует компиляции / установки, или вы можете просто включить его в свои скрипты на Python)
Сорин,
9
@Sorin: lxml - это оболочка поверх библиотеки C libxml2 и, следовательно, не является чистым Python.
Эли Кортрайт 07
2
@eli Именно то, что я хотел подчеркнуть, это может никому не подойти.
sorin 08
1
Ошибки проверки не удобны для пользователя. Как мне это сделать? mailman-mail5.webfaction.com/pipermail/lxml/2012-April/… не помогает.
None-da
Этот ответ все еще актуален?
Человек
27

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

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

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

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

пабигот
источник
12

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

Кому
источник
У меня есть 3 файла xsd, только когда присутствуют все 3 файла xsd, я могу проверить xml ... можно ли это сделать с помощью вашего метода?
Naveen
9

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