从Sax到Dom与DTD(Python)

1 投票
1 回答
767 浏览
提问于 2025-04-15 17:02

我需要一个经过验证的DOM树,并且要有DTD(这样才能使用getElementById)。验证和解析都能正常工作,但DOM却不太对劲:

from xml.dom import minidom 
from xml.dom.pulldom import SAX2DOM
from lxml import etree
import lxml.sax
from StringIO import StringIO

data_string = """\
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ELEMENT foo (bar)*>
<!ELEMENT bar (#PCDATA)>
<!ATTLIST bar id ID #REQUIRED>]><foo><bar id="nr_0">text</bar></foo> 
"""

#parser, with vali. at parsing
etree_parser = etree.XMLParser(dtd_validation=True,attribute_defaults=True) 
#parse it
sax_tree = etree.parse(StringIO(data_string),etree_parser);
handler = SAX2DOM();
lxml.sax.saxify(sax_tree,handler);
domObject = handler.document;

print domObject.getElementById("nr_0");
#returns None

print minidom.parseString(data_string).getElementById("nr_0");
#returns <DOM Element: bar at 0x7f36b77dc0e0>

看起来SAX2DOM没有把DTD传递给DOM。我是不是漏掉了什么?我听说在DOM构建完成后加载DTD是不可能的。

有没有什么想法?

1 个回答

1

根据我的了解:SAX DTD事件不是由ContentHandler处理的,而是由DTDHandler来处理,这是你可以在sax解析器(XMLReader)上设置的一个属性。这意味着你不能在不序列化和重新解析文档的情况下做到这一点。

validated_string = etree.tostring(tree)
domDocument = minidom.parseString(validated_string)

另一方面:除非你真的需要一个minidom文档,否则最好还是继续使用lxml树。(你可以使用xpath来实现类似于getElementById的功能,或者看看etree.XMLDTDIDetree.parseid

撰写回答