如何用xml.etree处理外部实体,像lxml.etree一样

5 投票
2 回答
5173 浏览
提问于 2025-04-17 14:58

我有一个脚本,用来解析XML文件,使用的是 lxml.etree 这个库:

from lxml import etree

parser = etree.XMLParser(load_dtd=True, resolve_entities=True)
tree = etree.parse('main.xml', parser=parser)

我需要设置 load_dtd=Trueresolve_entities=True,这样才能从 globals.xml 中解析出 &emptyEntry;

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE map SYSTEM "globals.xml" [
    <!ENTITY dirData "${DATADIR}"> 
]>
<map 
    xmlns:map="http://my.dummy.org/map"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsschemaLocation="http://my.dummy.org/map main.xsd"
>

  &emptyEntry; <!-- from globals.xml -->

  <entry><key>KEY</key><value>VALUE</value></entry>
  <entry><key>KEY</key><value>VALUE</value></entry>
</map>

使用的是 globals.xml

<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY emptyEntry "<entry></entry>">

现在我想把这个从非标准的 lxml 转换到标准的 xml.etree。但是这样做的时候,我的文件就出问题了,因为 xml.etree 不支持 load_dtd=Trueresolve_entities=True

有没有什么方法可以在 xml.etree 中解决这些实体的问题呢?

2 个回答

1

我的小窍门是使用一个外部程序叫做xmllint。

proc = subprocess.Popen(['xmllint','--noent',fname],stdout=subprocess.PIPE)
output = proc.communicate()[0]
tree = ElementTree.parse(StringIO.StringIO(output))
0

lxml是个很合适的工具。

不过,如果你想用标准库,那就要做好遇到困难的准备,并看看XMLParser的UseForeignDTD方法。这里有一个不错(但有点小技巧)的例子:Python ElementTree支持解析未知的XML实体吗?

撰写回答