XML/SAX: Externe Entities in Python code einbetten
Verfasst: Freitag 3. September 2004, 13:15
Oft will man mit möglichst wenig Dateien auskommen. Da bietet es sich an, externe Entities direkt in den Python Code einzubetten. Am Beispiel von eingebetteten DTDs zeigt der folgende Code Schnippsel wie das zu erreichen ist.
Der erste Schritt ist eine eigene Implementation des Entity Resolvers zu schreiben. Dieser gibt die eingebettete Entity zurück, falls vorhanden. Wenn die Entity nicht vorhanden ist, wird der original Resolver bemüht.
Die eingebetteten Entities wurden mit zlib komprimiert und mit Base64 kodiert eingebettet. Bereits beim Laden des Pythonmoduls werden die Entities entpackt.
Die Anwendung des neuen Resolvers sieht nun so aus:
Die Entities können mit dem folgenden lambda für das Einbetten vorbereitet werden:
Gruss, Andy
Der erste Schritt ist eine eigene Implementation des Entity Resolvers zu schreiben. Dieser gibt die eingebettete Entity zurück, falls vorhanden. Wenn die Entity nicht vorhanden ist, wird der original Resolver bemüht.
Die eingebetteten Entities wurden mit zlib komprimiert und mit Base64 kodiert eingebettet. Bereits beim Laden des Pythonmoduls werden die Entities entpackt.
Code: Alles auswählen
import xml.sax
from zlib import decompress
from base64 import decodestring
from StringIO import StringIO # cStringIO works too...
__myfirst_dtd = decompress(decodestring("""
eNqzUXT1cfV19QtRyK2syM1JyU82VNBQDnB2cQxx1LQDAIl5CKU=""" ))
__mysecond_dtd = decompress(decodestring("""
eNqzUXT1cfV19QtRyK2syM1JyU82UtBQDnB2cQxx1LQDAImFCKY=""" ))
# Translation dictionary for internal DTDs
INTERNAL_DTD = { 'myfirst.dtd' : __myfirst_dtd,
'mysecond.dtd': __mysecond_dtd }
class OwnEntityResolver(xml.sax.handler.EntityResolver):
""" Own external entity resolver returns embedded entities """
def __init__(self, oldresolver):
self.oldresolver = oldresolver
def resolveEntity(self, publicId, systemId):
if INTERNAL_DTD.has_key(systemId):
insrc = xml.sax.InputSource()
insrc.setByteStream(StringIO(INTERNAL_DTD[systemId]))
return insrc
else:
return self.oldresolver.resolveEntity(publicId, systemId)
Code: Alles auswählen
handler = SpamXmlHandler()
parser = xml.sax.make_parser()
parser.setContentHandler(handler)
# install own entity-Resolver
res = OwnEntityResolver(parser.getEntityResolver())
parser.setEntityResolver(res)
# finally parse it!
result = parser.parse(file)
Code: Alles auswählen
embedding = lambda data: base64.encodestring(zlib.compress(data, 9))