2016-08-29 1 views
1

Ich ist neu Überlauf zu stapeln, so „hallo“ zu everbody, und ich hoffe, dass jemand mir mit meiner Frage helfen kann ...Python lxml objektiviert: Seltsames Verhalten beim Wechsel eines Element schätzen

Kürzlich beginne ich zu spielen ein bisschen mit lxml.objectify und stolpere über das folgende Verhalten, das ich seltsam fand. Wenn ich erstellen Sie einfach eine kleine XML-Zeichenfolge wie folgt aus:

from lxml import objectify 

objroot = objectify.fromstring("<root>somerootvalue<child1/><child2/><child3/><child4><subchild1/><subchild2/></child4><child5><subchild1/><subchild2/></child5></root>") 
objroot.child4 = True 
objroot.child4.subchild1 = "Foo" 
objroot.child4.subchild2 = "Bar" 
print(objroot.child4.subchild1,objroot.child4.subchild2,objroot.child4) 

Der Ausgang ist nur: Foo Bar wahr

Wenn ich den Wert/Text der Elemente ändern dann durch:

from lxml import objectify 

objroot = objectify.fromstring("<root>somerootvalue<child1/><child2/><child3/><child4><subchild1/><subchild2/></child4><child5><subchild1/><subchild2/></child5></root>") 
objroot.child4 = True 
objroot.child4.subchild1 = "Foo" 
objroot.child4.subchild2 = "Bar" 
print(objroot.child4.subchild1,objroot.child4.subchild2,objroot.child4) 
objroot.child4 = False 
objroot.child4.subchild1 = "Foo" 
objroot.child4.subchild2 = "Bar" 
print(objroot.child4.subchild1,objroot.child4.subchild2,objroot.child4) 

der Ausgang ist wie erwartet: Foo Bar wahr, Foo Baz falsch

Aber wenn ich nur den Wert von objroot.ch ändern ild4 und die Druck Anweisung aufrufen, bekam Ive den folgenden Fehler:

from lxml import objectify 

objroot = objectify.fromstring("<root>somerootvalue<child1/><child2/><child3/><child4><subchild1/><subchild2/></child4><child5><subchild1/><subchild2/></child5></root>") 
objroot.child4 = True 
objroot.child4.subchild1 = "Foo" 
objroot.child4.subchild2 = "Bar" 
print(objroot.child4.subchild1,objroot.child4.subchild2,objroot.child4) 
objroot.child4 = False 
objroot.child4.subchild1 = "Foo" 
objroot.child4.subchild2 = "Bar" 
print(objroot.child4.subchild1,objroot.child4.subchild2,objroot.child4) 
objroot.child4 = True 
print(objroot.child4.subchild1,objroot.child4.subchild2,objroot.child4) 
File "src\lxml\lxml.objectify.pyx", line 450, in lxml.objectify._lookupChildOrRaise (src\lxml\lxml.objectify.c:6586) 
AttributeError: no such child: subchild1 

Während ich die letzte Ausgabe als „Foo Bar true“ erwarten, Ive bekam das „kein solches Kind Fehler“. So scheint es, dass der restliche Teil des Baumes hinter child4 abgeschnitten wurde? Ist das ein gewünschtes Verhalten, und wenn ja, wie kann ich den Text eines Elements in der Mitte des Baumes ändern, ohne den Rest zu schneiden?

Vielen Dank für Ihre Hilfe!

Antwort

1

Es ist eigentlich nicht so seltsam Verhalten, wenn wir uns ein wenig damit beschäftigen. Die Verwendung von root.element.subelement.... funktioniert nicht so, wie Sie annehmen könnten. Wir können etree verwenden, um den Status des XML-Baums auszudrucken und die Struktur zu überprüfen.

from lxml import objectify, etree 

objroot = objectify.fromstring("<root>somerootvalue<child1/><child2/><child3/><child4><subchild1/><subchild2/></child4><child5><subchild1/><subchild2/></child5></root>") 

print(etree.tostring(objroot, pretty_print=True) 

#output: 
<root>somerootvalue 
    <child1/> 
    <child2/> 
    <child3/> 
    <child4><subchild1/><subchild2/></child4> 
    <child5><subchild1/><subchild2/></child5> 
</root> 

Das sieht korrekt aus. Was passiert also, wenn wir objroot.child4 = True anrufen? Die API ermöglicht dies, aber es fügt nicht nur den Text hinzu. Vielmehr ersetzt es alles, was unter child4 mit dem Text war. Also werden die Unterelemente fallen gelassen. Wir können mit überprüfen:

objroot.child4 = True 
print(etree.tostring(objroot, pretty_print=True) 

#output: 
<root>somerootvalue 
    <child1/> 
    <child2/> 
    <child3/> 
    <child4 xmlns:py="..." py:pytype="bool">true</child4> 
    <child5><subchild1/><subchild2/></child5> 
</root> 

So ist es den Wert von child4 zu True gesetzt hat, aber es hat die Subelemente gesunken. Danach, wenn Sie die Werte der Teilelemente gesetzt werden:

objroot.child4.subchild1 = "Foo" 
objroot.child4.subchild2 = "Bar" 

Es schafft tatsächlich jedes Subelement unter child4 und setzt dann den Wert im Fluge.

Verwandte Themen