Python解析XML时如何忽略原有DTD并使用本地DTD文件?
问题:解析Evernote ENEX文件时遇到
nbsp实体未定义错误 重新学习Python,编写代码解析Evernote的ENEX格式XML文件时遇到如下错误:
lxml.etree.XMLSyntaxError: Entity 'nbsp' not defined, line 68908, column 61176
对应的解析代码为:
mytree = ET.parse(PATH TO THE ENEX FILE)
已将官方DTD文件复制到本地,并添加了将nbsp转为空格的实体,但不想修改每个待解析的ENEX文件,询问是否可以忽略ENEX文件中指定的DTD,转而使用本地提供的DTD文件。
解决方案
可以通过lxml的解析器配置实现忽略远程DTD并使用本地DTD,以下是具体实现方式:
方法一:通过自定义解析器加载本地DTD
创建禁用外部资源加载的解析器,同时加载本地DTD进行验证,无需修改原文件:from lxml import etree # 配置解析器:禁止网络请求,允许加载本地DTD并解析实体 parser = etree.XMLParser( no_network=True, load_dtd=True, resolve_entities=True ) # 加载本地DTD文件 local_dtd = etree.DTD("./evernote-export3.dtd") # 使用解析器解析ENEX文件 tree = etree.parse("your_target.enex", parser=parser) # 可选:验证文档是否符合本地DTD规范 is_valid = local_dtd.validate(tree)方法二:内存中替换DTD引用后解析
在读取文件内容时,将原文件中的远程DTD引用替换为本地路径,全程在内存中操作,不修改原文件:from lxml import etree parser = etree.XMLParser(resolve_entities=True) local_dtd_path = "./evernote-export3.dtd" # 读取文件并替换DTD引用 with open("your_target.enex", "r", encoding="utf-8") as f: content = f.read().replace( 'DOCTYPE en-export PUBLIC "-//Evernote//DTD Export//EN//3.0" "http://xml.evernote.com/pub/evernote-export3.dtd"', f'DOCTYPE en-export SYSTEM "{local_dtd_path}"' ) # 解析修改后的内容 tree = etree.fromstring(content.encode("utf-8"), parser=parser)关键注意点
- 确保本地DTD文件中已正确添加
nbsp实体定义,例如:<!ENTITY nbsp " "> no_network=True参数会阻止解析器尝试加载远程DTD,避免网络依赖和原DTD的缺失问题- 两种方法均无需修改原始ENEX文件,不会影响源数据
- 确保本地DTD文件中已正确添加
内容的提问来源于stack exchange,提问作者Mark S.
相关产品推荐
相关产品推荐

