首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Python和lxml根据外部DTD验证XML

使用Python和lxml根据外部DTD验证XML
EN

Stack Overflow用户
提问于 2014-03-13 22:18:04
回答 2查看 3.9K关注 0票数 3

我试图根据doctype标记中引用的外部DTD验证XML文件。具体地说:

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export3.dtd">
...the rest of the document...

我正在使用Python3.3和lxml模块。通过阅读http://lxml.de/validation.html#validation-at-parse-time,我把这些都放在了一起:

代码语言:javascript
运行
复制
enexFile = open(sys.argv[2], mode="rb") # sys.argv[2] is the path to an XML file in local storage.
enexParser = etree.XMLParser(dtd_validation=True)
enexTree = etree.parse(enexFile, enexParser)

根据我对validation.html的了解,lxml库现在应该负责检索DTD并执行验证。但相反,我明白了:

代码语言:javascript
运行
复制
$ ./mapwrangler.py validate notes.enex
Traceback (most recent call last):
  File "./mapwrangler.py", line 27, in <module>
    enexTree = etree.parse(enexFile, enexParser)
  File "lxml.etree.pyx", line 3239, in lxml.etree.parse (src/lxml/lxml.etree.c:69955)
  File "parser.pxi", line 1769, in lxml.etree._parseDocument (src/lxml/lxml.etree.c:102257)
  File "parser.pxi", line 1789, in lxml.etree._parseFilelikeDocument (src/lxml/lxml.etree.c:102516)
  File "parser.pxi", line 1684, in lxml.etree._parseDocFromFilelike (src/lxml/lxml.etree.c:101442)
  File "parser.pxi", line 1134, in lxml.etree._BaseParser._parseDocFromFilelike (src/lxml/lxml.etree.c:97069)
  File "parser.pxi", line 582, in lxml.etree._ParserContext._handleParseResultDoc (src/lxml/lxml.etree.c:91275)
  File "parser.pxi", line 683, in lxml.etree._handleParseResult (src/lxml/lxml.etree.c:92461)
  File "parser.pxi", line 622, in lxml.etree._raiseParseError (src/lxml/lxml.etree.c:91757)
lxml.etree.XMLSyntaxError: Validation failed: no DTD found !, line 3, column 43

这让我感到惊讶,因为如果我关闭了验证,那么文档就会很好地解析,我可以做print(enexTree.docinfo.doctype)来获得

代码语言:javascript
运行
复制
$ ./mapwrangler.py validate notes.enex
<!DOCTYPE en-export SYSTEM "http://xml.evernote.com/pub/evernote-export3.dtd">

所以在我看来,找到DTD应该没什么问题。

谢谢你的帮助。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-03-14 14:40:49

在构造解析器对象时需要添加no_network=False。默认情况下,此选项设置为True

来自http://lxml.de/parsing.html#parsers解析器选项的文档

no_network -在查找外部文档时阻止网络访问(默认情况下)

票数 3
EN

Stack Overflow用户

发布于 2016-09-08 08:08:46

出于一个我仍然不知道的原因,我的问题与XML目录在我的本地文件系统中的位置有关。

在我的例子中,我使用了一个与组件内容管理系统(CCMS,本例中的SDL 2011 R2)紧密集成的XML编辑器。当编辑器连接到CCMS时,DTD、目录文件和一组其他文件被同步。这些文件最终出现在本地文件系统上:

代码语言:javascript
运行
复制
C:\Users\[username]\AppData\Local\Trisoft\InfoShare Client\[id]\Config\DocTypes\catalog.xml

我不能让它起作用。只需将整个目录复制到另一个固定的位置,就可以了:

代码语言:javascript
运行
复制
f = r"path/to/my/file.xml"
# set XML catatog file path
os.environ['XML_CATALOG_FILES'] = r'C:\DATA\Mydoctypes\catalog.xml'
# configure parser
parser = etree.XMLParser(dtd_validation=True, no_network=True)
# validate
try:
   valid = etree.parse(f, parser=parser)
    print("This file is valid against the DTD.")
except etree.XMLSyntaxError, error:
   print("This file is INVALID against the DTD!")
   print(error)

显然,这并不理想,但它有效。

这可能与文件权限有关,还是Windows中的旧“文件路径太长”问题?我还没有尝试过一个象征性的链接是否会起作用。

我使用的是Windows 7,Python2.7.11,而lxml的版本是(3.6.0)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22392180

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档