【发布时间】:2015-08-08 20:15:52
【问题描述】:
我正在尝试在 Python 3.4 中检查 XML 文件(针对 DTD、实体、处理指令、命名空间)的有效性。
查看 Python 文档,三个 Python XML 模块 pyexpat、ELementTree 和 SAX 的默认底层解析器是 expat。在 Pyexpat 页面 (https://docs.python.org/3.4/library/pyexpat.html?highlight=pyexpat#module-xml.parsers.expat) 上说使用了非验证版本的 expat 解析器: “xml.parsers.expat 模块是 Expat 非验证 XML 解析器的 Python 接口。”然而,与此同时,当您查看 Python 中的 SAX 文档时,您会看到所有这些用于启用 DTD 验证等的处理函数。您到底是如何让它们工作的?
但是,根据这篇帖子Parsing XML Entity with python xml.sax SAX 可以验证。显然用 expat 作为解析器。
我已经重用了这篇文章中的代码,但无法让它工作我收到错误说 expat 不支持验证: “文件“/usr/lib/python3.4/xml/sax/expatreader.py”,第 149 行,在 setFeature 中 “外籍人士不支持验证”) xml.sax._exceptions.SAXNotSupportedException: expat 不支持验证”。 在帖子中使用了 Python 2.5,所以也许 SAX 从那时起发生了变化......
这是代码:
import xml.sax
from xml.sax import handler, make_parser, parse
import os
import collections
class SaxParser():
# initializer with directory part as argument
def __init__(self, dir_path):
self.dir_path = dir_path
def test_each_file(self, file_path):
# ensure full file name is shown
rev = file_path[::-1] # reverse string file_path to access position of "/"
file = file_path[-rev.index("/"):]
try:
f = open(file_path, 'r', encoding="ISO-8859-1") # same as "latin-1" encoding
# see this for enabling validation:
# https://stackoverflow.com/questions/6349513/parsing-xml-entity-with-python-xml-sax
parser = make_parser() # default parser is expat
parser.setContentHandler(handler.ContentHandler())
parser.setFeature(handler.feature_namespaces,True)
parser.setFeature(handler.feature_validation,True)
parser.setFeature(handler.feature_external_ges, True)
parser.parse(f)
f.close()
return (file, "OK")
except xml.sax.SAXParseException as PE:
column = PE.getColumnNumber()
line = PE.getLineNumber()
msg = PE.getMessage()
value = msg + " " + str(line) + " " + str(column)
return (file, value)
except ValueError:
return (file, "ValueError. DTD uri not found.") # that can happen
def test_directory_sax(self, dir_path):
tuples = []
for ind, file in enumerate(os.listdir(dir_path), 1):
if file.endswith('.xml'):
tuples.append(self.test_each_file(dir_path + file))
# convert into dict and sort it by key (file number)
dict_of_errors = dict(tuples)
dict_of_errors = collections.OrderedDict(sorted(dict_of_errors.items()))
return dict_of_errors
# ========================================================================
# INVOKE TESTS FOR SINGLE SPECIFIED DIRECTORY THAT CONTAINS TEST FILES
# ========================================================================
path = # path to directory where xml file is. - not the filepath!
single_sax = SaxParser(path)
print('============================================================')
print('TEST FOR SAX parser FOR DIRECTORY ' + path)
print('============================================================\n')
print(single_sax.test_directory_sax(path))
和测试xml文件(应该产生验证错误):
<!DOCTYPE root [
<!ATTLIST root
id2 ID "x23"
>
]>
<!-- an ID attribute must have a declared default
of #IMPLIED or #REQUIRED
-->
<root/>
如何检查有效性?对于三个 XML 模块之一? 一个简单的例子就可以了。
谢谢。
【问题讨论】:
标签: python xml validation parsing