Python lxml objectify:更改元素值时的奇怪行为

时间:2016-08-29 14:46:26

标签: python python-3.x attributeerror lxml.objectify

我是堆叠溢出的新手,所以对任何人都“嗨”,我希望有人可以帮我解决我的问题......

最近我开始玩lxml.objectify并且偶然发现以下行为,我发现这很奇怪。 如果我只是创建一个像这样的小xml字符串:

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)

输出只是:Foo Bar true

如果我更改元素的值/文本,则按:

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)

输出符合预期:     Foo Bar真的,     Foo Baz假

但是,如果我只是更改objroot.child4的值并调用print语句,我收到以下错误:

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

虽然我希望最后一个输出是“Foo Bar true”,但我得到了“没有这样的孩子错误”。 所以看来child4后面的树的剩余部分已被切断了?这是一个理想的行为,如果是的话,我怎样才能更改树中间元素的文本而不删除其余部分?

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

一旦我们深入挖掘它,实际上并没有那种奇怪的行为。使用grep -Ff file1 file2 的效果并不像您可能认为的那样。我们可以使用root.element.subelement....打印出xml树的状态并检查结构。

etree

这看起来是正确的。那么当我们打电话给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> 时会发生什么? API允许您执行此操作,但它不仅仅是添加文本。相反,它用文本替换objroot.child4 = True下的所有内容。因此子元素被删除。我们可以使用:

查看
child4

因此,它已将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> 的值设置为child4,但它已删除了子元素。之后,当您使用以下设置子元素的值时:

True

它实际上在objroot.child4.subchild1 = "Foo" objroot.child4.subchild2 = "Bar" 下创建每个子元素,然后动态设置值。