Python SAX Parser: resolveEntity
Мне сложно понять, как привязать собственный ResolveEntityHandler к парсеру SAX. На ТАК есть этот ответ. Но, к сожалению, я не могу воспроизвести там результат.
Когда я запускаю следующий код, который фактически скопирован из вышеупомянутого ответа, только что обновленного до Python 3,
import io
import xml.sax
from xml.sax.handler import ContentHandler
# Inheriting from EntityResolver and DTDHandler is not necessary
class TestHandler(ContentHandler):
# This method is only called for external entities. Must return a value.
def resolveEntity(self, publicID, systemID):
print ("TestHandler.resolveEntity(): %s %s" % (publicID, systemID))
return systemID
def skippedEntity(self, name):
print ("TestHandler.skippedEntity(): %s" % (name))
def unparsedEntityDecl(self, name, publicID, systemID, ndata):
print ("TestHandler.unparsedEntityDecl(): %s %s" % (publicID, systemID))
def startElement(self, name, attrs):
summary = attrs.get('summary', '')
print ('TestHandler.startElement():', summary)
def main(xml_string):
try:
parser = xml.sax.make_parser()
curHandler = TestHandler()
parser.setContentHandler(curHandler)
parser.setEntityResolver(curHandler)
parser.setDTDHandler(curHandler)
stream = io.StringIO(xml_string)
parser.parse(stream)
stream.close()
except xml.sax.SAXParseException as e:
print ("ERROR %s" % e)
XML = """<!DOCTYPE test SYSTEM "test.dtd">
<test summary='step: #'>Entity: ¬</test>
"""
main(XML)
и внешний test.dtd
<!ENTITY num "FOO">
<!ENTITY pic SYSTEM 'bar.gif' NDATA gif>
Что у меня есть
TestHandler.startElement(): step:
TestHandler.skippedEntity(): not
Process finished with exit code 0
Итак, мои вопросы:
- почему
resolveEntity
никогда не звонил? - как привязать ResolveEntityHandler к вашему парсеру?
1 ответ
То, что вы видите, связано с изменением в Python 3.7.1:
Изменено в версии 3.7.1: синтаксический анализатор SAX больше не обрабатывает общие внешние сущности по умолчанию для повышения безопасности. Раньше парсер создавал сетевые подключения для извлечения удаленных файлов или загружал локальные файлы из файловой системы для DTD и сущностей. Функцию можно снова включить с помощью метода
setFeature()
на объекте парсера и аргументеfeature_external_ges
.
Чтобы добиться того же поведения, что и в более ранних версиях, добавьте следующие строки:
from xml.sax.handler import feature_external_ges
и (в main
функция)
parser.setFeature(feature_external_ges, True)