113

我在另一个文件中有一个 XML 文件和一个 XML 模式,我想验证我的 XML 文件是否符合该模式。我如何在 Python 中做到这一点?

我更喜欢使用标准库的东西,但如有必要,我可以安装第三方包。

4

8 回答 8

64

我假设您的意思是使用 XSD 文件。令人惊讶的是,支持这一点的 python XML 库并不多。但是,lxml 确实如此。使用 lxml检查验证。该页面还列出了如何使用 lxml 来验证其他模式类型。

于 2008-11-18T18:16:53.587 回答
32

Python3 中使用流行库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 进行验证

于 2016-06-22T15:14:40.473 回答
27

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

  • pyxsd,描述说它使用xml.etree.cElementTree,它不是“纯python”(但包含在stdlib中),但源代码表明它回退到xml.etree.ElementTree,所以这将被视为纯python。没有使用它,但根据文档,它确实进行了模式验证。
  • minixsv : '一个用“纯” Python 编写的轻量级 XML 模式验证器'。然而,描述说“目前支持 XML 模式标准的一个子集”,所以这可能还不够。
  • XSV,我认为它用于 W3C 的在线 xsd 验证器(它似乎仍然使用旧的 pyxml 包,我认为它已不再维护)
于 2011-04-06T12:53:52.580 回答
19

您可以使用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))
于 2018-09-13T09:30:12.083 回答
13

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

于 2009-12-22T12:54:33.477 回答
13

有两种方法(实际上还有更多)可以做到这一点。
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

于 2015-08-26T13:51:27.637 回答
7

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)) 
于 2008-11-18T18:09:40.027 回答
1
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')
于 2021-06-23T07:37:24.943 回答