繁体   English   中英

Python lxml.etree 保留实体引用

[英]Python lxml.etree retain entity references

我正在创建一个简单的脚本来使用特定模式解析、验证、修复和重新打印 XML 文件。 整个事情都很好,但问题是当我打印修改后的 ElementTree 时,它会删除我所有的实体引用。

这是简化的 python 代码:

from pathlib import Path

from lxml import etree as ET
from lxml.builder import E

schema = ET.XMLSchema('C:/path/to/schema.xsd')
parser = ET.XMLParser(recover=True)
source_file = Path('file.xml')
tree = ET.parse(source_file.name, parser, base_url="http://www.domain.url")
root = tree.getroot()

# Do some validation

source_file.write_text(ET.tostring(tree, encoding='utf-8').decode(encoding='utf-8'), encoding='utf-8') 

这是“之前”XML 的片段:

<!DOCTYPE element [
<!ENTITY % ISOEntities PUBLIC "ISO 8879-1986//ENTITIES ISO Character Entities 20030531//EN//XML" "http://www.domain.url/path/to/ISOEntities"> 
%ISOEntities
]>
<para>&minus;67 to 250&deg;</para>

之后:

<!DOCTYPE element [
<!ENTITY % ISOEntities PUBLIC "ISO 8879-1986//ENTITIES ISO Character Entities 20030531//EN//XML" "http://www.domain.url/path/to/ISOEntities"> 
<! -- THE ENTIRE CONTENTS OF ISOENTITIES (100s of lines of code) -->
]>
<para>-67 to 250°</para>

虽然技术上“正确”,但我想将它们保留为实体引用而不是文字字符。 如前所述,它还解决了我不想要的ISOEntities

现在,我尝试的明显解决方案是将resolve_entities=False kwarg 添加到解析器。 结果是完全删除了引用并简单地将它们替换为空。

<!DOCTYPE element [
<!ENTITY % ISOEntities PUBLIC "ISO 8879-1986//ENTITIES ISO Character Entities 20030531//EN//XML" "http://www.domain.url/path/to/ISOEntities"> 
%ISOEntities
]>
<para>67 to 250</para>

有什么方法可以将树打印成字符串,就像它被解析时一样? (即保持 internalDTD 相同并保持实体引用不变)

编辑:使用调试器在tostring操作之前验证实体是否丢失,因此肯定是解析过程消除了它们,而不是转换为字符串。

所以我没有找到这个问题的好答案。 实体都在 %IsoEntities 中声明,但因为它本身也是一个实体,并且我将其设置为不解析实体,所以解析器不解析 %IsoEntities,因此也不识别任何其他实体。

但我确实找到了解决方法。 结果是&amp; 不会被替换,我猜是因为它是一个独特的案例。 所以解决方法是将所有&替换为&amp; . 所以你会发送类似&amp;minus;的东西。 . 解析器不会将其识别为实体,并将保持原样。 一旦ElementTree被转换成字符串格式,就可以再次通过go并替换所有&amp; &所以你最终再次得到你原来的实体。

我仍然很想听听是否有人有更好的答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM