In questi giorni, lavorando con la libreria ElementTree, mi sono accorto che manca del supporto per le entità XML esterne. Quelle interne funzionano senza problemi, ma le altre danno qualche problema poiché le risorse non vengono espanse in fase di parsing.
Non so se a qualcuno possa interessare, ma ho scritto qualche riga di workaround per far gestire correttamente le entità esterne anche ad ElementTree senza applicare una patch ai sorgenti. Il codice seguente si applica alla classe iterparse, ma può facilmente essere modificato per applicarsi al parser XML standard estendendo la classe appropriata:
from xml.parse import expat
from elementtree import ElementTree
class ExternalEntitiesIterparse(ElementTree.iterparse):
""" Custom iterparser that handles also external entities.
"""
def __init__(self, source, events=None):
super(ElementTree.iterparse, self).__init__(source, events)
parser = self._parser._parser
parser.UseForeignDTD(False)
parser.SetParamEntityParsing( expat.XML_PARAM_ENTITY_PARSING_ALWAYS)
parser.ExternalEntityRefHandler = self._extRef
def _extRef(self, context, base, systemId, publicId):
""" Handle an external entity
"""
entitiesParser = self._parser._parser.ExternalEntityParserCreate( context )
if base is None and False:
path = systemId
else:
path = os.path.join( base, systemId )
entitiesPath = os.path.abspath( path )
entitiesParser.Parse( file(entitiesPath).read() )
return 1
Ora ExternalEntitiesIterparse può essere utilizzato come iterparse senza doversi preoccupare delle entità estene, che verranno correttamente espanse.