2015-09-16 16 views
7

Ich bin ein wenig verwirrt durch einige der Design-Entscheidungen in der Python-ElementTree-API - sie scheinen irgendwie willkürlich, so würde ich gerne eine Klärung, um zu sehen, ob diese Entscheidungen einige Logik hinter sich haben sie, oder wenn sie nur mehr oder weniger ad hoc sind.Python ElementTree: ElementTree vs root Element

Im Allgemeinen gibt es zwei Möglichkeiten, wie Sie eine ElementTree erzeugen können - eine über eine Art Quellstrom, wie eine Datei oder einen anderen I/O-Stream. Dies wird über die parse() Funktion oder die ElementTree.parse() Klassenmethode erreicht.

Eine andere Möglichkeit besteht darin, das XML direkt von einem Zeichenfolgenobjekt zu laden. Dies kann über die Funktion fromstring() erfolgen.

Okay, großartig. Nun würde ich denken, dass diese Funktionen im Wesentlichen identisch sind in Bezug auf was sie zurückgeben - der Unterschied zwischen den beiden ist im Grunde die Quelle der Eingabe (man nimmt eine Datei oder Stream-Objekt, die andere nimmt eine einfache Zeichenfolge) ein Grund gibt die parse() Funktion ein ElementTree Objekt zurück, aber die fromstring() Funktion gibt ein Element Objekt zurück. Der Unterschied ist im Grunde, dass das Element Objekt das Wurzel Element einer XML-Struktur ist, während das ElementTree Objekt eine Art "Wrapper" um das Wurzelelement ist, das einige zusätzliche Features bietet. Sie können das Stammelement immer von einem ElementTree-Objekt abrufen, indem Sie getroot() aufrufen.

Dennoch bin ich verwirrt, warum wir diese Unterscheidung haben. Warum gibt fromstring() ein Wurzelelement direkt zurück, aber parse() gibt ein Objekt ElementTree zurück? Gibt es eine Logik hinter dieser Unterscheidung?

+1

Ehrlich zu schreiben, die 'ElementTree' API einige wirklich seltsame Entscheidungen zu Zeiten hat, und Das ist einer von ihnen. – gsnedders

+0

Ich arbeite mit lxml und die api ist das gleiche. Auch ich würde gerne die Antwort auf diese Fragen wissen. Ich tendiere dazu, die Dinge auf der Wrapper-Ebene zu halten, aber ich weiß nicht warum. –

+1

ElementTree hat mehr Funktionen als Element, vor allem 'write()'.Ich sage nicht, dass diese nicht für Element zur Verfügung gestellt werden könnten, aber sie sind große Unterschiede. 'fromstring()', die nur ein Element enthält, verhindert effektiv das Ändern und Schreiben des Baumes. – remram

Antwort

0

Ich denke das gleiche wie remam in den Kommentaren: Parse nimmt einen Speicherort oder ein Dateiobjekt und bewahrt diese Informationen, so dass es zusätzliche Dienstprogramm zur Verfügung stellen kann, was wirklich hilfreich ist. Wenn parse kein ET-Objekt zurückgibt, dann müssten Sie die Quellen besser verfolgen und was nicht, um sie manuell wieder in die Hilfsfunktionen einzufügen, die ET-Objekte standardmäßig haben. Im Gegensatz zu Dateien, Strings per Definition haben nicht die gleiche Art von Informationen von ihnen angehängt, so dass Sie nicht die gleichen Dienstprogramme für sie erstellen können (sonst gibt es sehr gut eine ET.parsefromstring() Methode, die würde ein ET-Objekt zurückgeben).

Ich vermute, dies ist auch die Logik hinter der Methode Parse statt ET.fromfile genannt wird(): Ich würde erwarten, dass die gleichen Objekttyp von FROMFILE und zurückgegeben werden vonString, kann aber sage nicht, dass ich dasselbe von Parse erwarten würde (es ist eine lange Zeit seit ich ET benutzt habe, also gibt es keine Möglichkeit, das zu überprüfen, aber das ist mein Gefühl).

Zum Thema Remram ausgelöst, Dienstprogramm-Methoden auf Elemente platzieren, wie ich die Dokumentation verstehe, sind Elemente sehr einheitlich, wenn es um die Umsetzung geht. Die Leute sprechen von "Wurzelelementen", aber das Element an der Wurzel des Baums ist buchstäblich mit allen anderen Elementen in Bezug auf seine Klasse Attribute und Methoden identisch. Soweit ich weiß, wissen die Elemente nicht einmal, wer ihre Eltern sind, was diese Einheitlichkeit wahrscheinlich unterstützen wird. Sonst könnte es mehr Code geben, um das "root" -Element zu implementieren (das keinen Elternteil hat) oder um Unterelemente neu zu parieren. Es scheint mir, dass die Einfachheit der Elementklasse sehr zu ihren Gunsten wirkt.Es scheint mir also besser zu sein, Elemente weitestgehend agnostisch von irgendetwas über ihnen zu lassen (ihre Eltern, die Datei, aus der sie stammen), so dass es keine Fehler bezüglich 4 Elemente mit verschiedenen Ausgabedateien im selben Baum (oder ähnlichem) geben kann.

Wenn es darum geht, das Modul innerhalb von Code zu implementieren, scheint es mir, dass das Skript die Eingabe als Datei irgendwann erkennen müsste, auf die eine oder andere Art (sonst würde es versuchen, die Datei zu übergeben fromstring). Es sollte also keine Situation entstehen, in der die Ausgabe parsen sollte sollte unerwartet sein, so dass der ElementTree als ein Element angenommen und als solches verarbeitet wird (es sei denn, parse wurde implementiert, ohne dass der Programmierer überprüft zu sehen was Parse tat, was mir gerade wie eine schlechte Angewohnheit scheint).

3

Eine schöne Antwort kommt von diesem alten discussion:

Nur für das Protokoll: Fredrik [der Schöpfer von ElementTree] nicht wirklich „Marotte“ es ein Design betrachten. Er argumentiert, dass es für verschiedene Anwendungsfälle konzipiert ist. Während parse() analysiert eine Datei, die normalerweise ein komplettes Dokument enthält (in ET als ElementTree-Objekt dargestellt), Fromstring() und vor allem die 'literal wrapper' XML() sind für die Analyse von Zeichenfolgen, die (die meisten ?) enthalten oft nur XML-Fragmente. Mit einem Fragment möchten Sie in der Regel weiterhin Dinge wie Einfügen in einen anderen Baum tun, so dass Sie in fast allen Fällen das Top-Level-Element benötigen.

Und:

Warum nicht der einzige Weg ist et.parse dies zu tun? Warum haben XML oder fromstring überhaupt?

Nun, Anwendungsfälle. XML() ist ein Alias ​​für vonString(), weil es bequem ist (und gut lesbar)

section = XML ('A bis Z') section.append (Tz)

für XML-Literale zu schreiben im Quellcode.() VonString ist es da, wenn Sie ein Fragment aus einer Zeichenfolge analysieren möchten, die Sie bekam von was auch immer Quelle, ist es einfach, dass auszudrücken mit genau dieser Funktion, wie in

el = fromstring(some_string) 

Wenn Sie ein analysieren möchten Dokument aus einer Datei oder einem dateiähnlichen Objekt verwenden Sie parse(). Drei Anwendungsfälle, drei Funktionen. Der vierte Anwendungsfall von ein Dokument aus einem String-Parsing nicht über seine eigene Funktion, weil es trivial ist

tree = parse(BytesIO(some_byte_string)) 
Verwandte Themen