[Python-de] String Interpolation in ElementTree implementieren

Florian Lindner mailinglists at xgm.de
Mo Okt 8 18:19:17 CEST 2012


Am Sonntag, 23. September 2012, 12:23:34 schrieb Florian Lindner:
> Hallo,
> 
> ich will erreichen, dass man in XML Ersetzungen einbetten kann, also:
> 
> <root filesystem="{filesystem}">
> {files}
> </root>
> 
> ich habe ein Dictionary repl = {"filesystem" : "btrfs", "files" :
> "whatever"} und würde das beim parsen des XML einfach mitgeben und bekomme
> dann die Strings schon fertig eingesetzt zurück. Ersetzt werden sollen
> Attribute und Text.
> 
> Hier fängt das Problem an. Als XML-API benutze ich ElementTree.
> 
> Das einfachste wäre wohl, wenn der ElementTree benutzende Code sich selber
> drum kümmert:  str = interpolate(node.attrib["filesystem"], repl). Oder halt
> einfach direkt .format aufruft.
> 
> Mir wäre es aber am liebsten, wenn ich das weitgehend transparent einbinden
> könnte. Wenn ich nun von xml.etree.ElementTree.ElementTree ableite und die
> Methoden text und attrib überschreibe, ok... Nur müsste ich wohl auch
> sämtliche Funktionen modifizieren, die ElementTrees zurückgeben (damit sie
> meine Kindklasse zurückgeben) und das wäre dann wohl doch recht viel
> Aufwand.

Soo, nochmal eine kleine Rückmeldung, wie ich es nun gemacht habe.

Ein Worker weiß selber, ob er Subworker hat (die den Kontext und damit die 
Ersetzungstabelle verändern können) oder nicht. Deshalb habe ich der 
Basisklasse aller Worker diese Funktion hinzugefügt:


    def do_string_interpolation(self, recurse=True):
        """ Replace all strings like {U} with the value from the context 
dictionary if it exists. Workers that can have subworkers should not recurse. 
"""
        if recurse:
            selection = ".//"
        else:
            selection = "."

        for n in self.config.findall(selection):
            try: n.text = n.text.format(**self.context)
            except (AttributeError, KeyError): pass
            for a in n.attrib:
                try: n.attrib[a] = n.attrib[a].format(**self.context)
                except KeyError: passttrib[a].format(**self.context)
                except KeyError: pass

Diese wird im Konstruktur aufgerufen. Damit Worker, die nicht rekursiv 
ersetzen wollen dies können:

class BaseWorker():
    """ Base Class for all workers. """
    
    def __init__(self, configuration, context, 
recursive_string_interpolation=True):

Diese müssen dann halt __init__ überschreiben und den Konstruktur mit False 
entsprechend aufrufen.

Viele Grüße,
Florian




Mehr Informationen über die Mailingliste python-de