在Python中使用XML模式进行验证


104

我在另一个文件中有一个XML文件和一个XML模式,我想验证我的XML文件是否遵循该模式。如何在Python中执行此操作?

我希望使用标准库,但如有必要,我可以安装第三方软件包。

Answers:


61

我假设您的意思是使用XSD文件。令人惊讶的是,没有很多支持此功能的python XML库。但是,lxml确实可以。使用lxml检查验证。该页面还列出了如何使用lxml与其他架构类型进行验证。


1
lxml是否是纯python?(需要编译/安装,也可以只将其包含在python脚本中)
sorin 2010年

9
@Sorin:lxml是libxml2 C库之上的包装,因此不是纯Python。
伊莱·考特赖特

2
@eli正是我要强调的内容,这可能不适合任何人。
索林2010年

1
验证错误不是用户友好的。我将如何处理?mailman-mail5.webfaction.com/pipermail/lxml/2012-April/…无济于事。
无-2012年

这个答案仍然是最新的吗?
人类

27

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

  • pyxsd,描述说它使用xml.etree.cElementTree,它不是“纯python”(但包含在stdlib中),但是源代码表明它回落到xml.etree.ElementTree,因此将其视为纯python。尚未使用它,但是根据文档,它确实进行模式验证。
  • minixsv:“用“纯” Python编写的轻量级XML模式验证器”。但是,描述中说“当前支持XML模式标准的子集”,所以这可能还不够。
  • XSV,我认为它用于W3C的在线xsd验证器(它似乎仍使用旧的pyxml包,我认为该包不再维护)

5
我将通过这些来看看PyXB。看起来大多数这些状态都不完整,而且看起来有些“死”。据我所知,pyxsd的最新更新时间是2006年,minixsv的更新时间是2008年,XSV的时间是2007年。并非总是最好的理由来考虑一个软件包而不是另一个软件包,但是我认为这种情况是合理的。
oob

2
PyXB +1。我在Django中使用它来验证在“管理”部分中插入的原始XML。简单易用。
tatlar

21

使用流行的库lxml的 Python3中的简单验证器的示例

安装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对象,因此:

验证器

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进行验证



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

您可以使用xmlschema Python软件包轻松地针对XML Schema(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))

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.