Validating with an XML schema in Python

I have an XML file and an XML schema in another file and I'd like to validate that my XML file adheres to the schema. How do I do this in Python?

I'd prefer something using the standard library, but I can install a third-party package if necessary.

142808 次浏览

lxml provides etree.DTD

from the tests on 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))

我假设您指的是使用 XSD 文件。令人惊讶的是,并没有多少 pythonXML 库支持这一点。但是 lxml 可以。检查 使用 lxml 进行验证。该页面还列出了如何使用 lxml 与其他架构类型进行验证。

http://pyxb.sourceforge.net/上的 PyXB 包从 XML 模式文档为 Python 生成验证绑定。它处理几乎每个模式构造并支持多个名称空间。

至于“纯 Python”解决方案: 包索引列表:

  • Pyxsd ,说明说它使用 xml.etree.cElementTree,它不是“纯 Python”(但包含在 stdlib 中) ,但源代码表明它回到 xml.etree.cElementTree。ElementTree,所以这可以算作纯 Python。还没用过,但根据文档,它确实做了模式验证。
  • Minixsv : ‘用“纯”Python 编写的轻量级 XML 模式验证器’。但是,描述说“目前支持 XML 模式标准的一个子集”,因此这可能还不够。
  • XSV ,我认为它用于 W3C 的在线 xsd 验证器(它似乎仍然使用旧的 pyxml 包,我认为它已经不再维护了)

有两种方法(实际上还有更多)可以做到这一点。
1. using 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. 在许多 Linux 发行版中都安装了 commandline.xmllint,可以使用其中的 Xmllint

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

Python 3中使用流行库 lxml的一个简单验证器示例

安装 lxml

pip install lxml

如果出现类似 ”在库 libxml2中找不到 xmlCheckVersion 函数。是否安装了 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! :(')

A little bit of OOP

为了验证多个文件,不需要每次都创建 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 进行验证

可以使用 Xmlschema Python 包轻松地根据 XML 架构(XSD)验证 XML 文件或树。它是纯 Python,可在 派派上使用,并且没有很多依赖项。

示例-验证一个文件:

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

如果文件没有针对 XSD 进行验证,该方法将引发一个异常。

If you want to validate many files you only have to load the XSD once:

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))
import xmlschema




def get_validation_errors(xml_file, xsd_file):
schema = xmlschema.XMLSchema(xsd_file)
validation_error_iterator = schema.iter_errors(xml_file)
errors = list()
for idx, validation_error in enumerate(validation_error_iterator, start=1):
err = validation_error.__str__()
errors.append(err)
print(err)
return errors


errors = get_validation_errors('sample3.xml', 'sample_schema.xsd')