You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 "&#160;">
    • no_network=True参数会阻止解析器尝试加载远程DTD,避免网络依赖和原DTD的缺失问题
    • 两种方法均无需修改原始ENEX文件,不会影响源数据

内容的提问来源于stack exchange,提问作者Mark S.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 13:32:40