在Python中用XML架构进行验证
我有一个XML文件,还有一个在另一个文件里的XML模式(schema),我想检查一下我的XML文件是否符合这个模式。请问我该怎么在Python中做到这一点呢?
我希望能用标准库里的工具,但如果需要的话,我也可以安装第三方的包。
8 个回答
41
你可以很简单地用一个叫做 xmlschema 的 Python 包 来验证一个 XML 文件或树是否符合 XML 模式(XSD)。这个包是纯 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))
43
一个使用流行库 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! :(')
一点面向对象编程
为了验证多个文件,我们不需要每次都创建一个 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 进行验证
73
我猜你是指使用XSD文件。令人惊讶的是,支持这个的Python XML库并不多。不过,lxml库是可以的。你可以查看一下lxml的验证功能。这个页面还列出了如何用lxml来验证其他类型的模式。