我在另一个文件中有一个 XML 文件和一个 XML 模式,我想验证我的 XML 文件是否符合该模式。我如何在 Python 中做到这一点?
我更喜欢使用标准库的东西,但如有必要,我可以安装第三方包。
我在另一个文件中有一个 XML 文件和一个 XML 模式,我想验证我的 XML 文件是否符合该模式。我如何在 Python 中做到这一点?
我更喜欢使用标准库的东西,但如有必要,我可以安装第三方包。
我假设您的意思是使用 XSD 文件。令人惊讶的是,支持这一点的 python XML 库并不多。但是,lxml 确实如此。使用 lxml检查验证。该页面还列出了如何使用 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! :(')
一点OOP
为了验证多个文件,不需要每次都创建一个XMLSchema对象,因此:
验证器.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
现在我们可以验证目录中的所有文件,如下所示:
主文件
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 进行验证
至于“纯python”解决方案:包索引列表:
您可以使用xmlschema Python 包轻松地根据 XML 模式 (XSD) 验证 XML 文件或树。它是纯 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))
http://pyxb.sourceforge.net/上的 PyXB 包从 XML 模式文档生成 Python 的验证绑定。它处理几乎所有模式构造并支持多个命名空间。
有两种方法(实际上还有更多)可以做到这一点。
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')
>> 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))
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')