【问题标题】:Python lxml objectify: Strange behaviour when changing an elements valuePython lxml objectify:更改元素值时的奇怪行为
【发布时间】:2017-01-05 15:37:04
【问题描述】:

我是堆栈溢出的新手,所以向大家“嗨”,我希望有人可以帮助我解决我的问题......

最近我开始玩弄 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)

输出如预期: 富吧真的, 富巴兹假

但是,如果我只是更改 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后面那棵树的剩余部分已经被砍掉了?这是一种理想的行为吗?如果是,我怎样才能在不剪切其余部分的情况下更改树中间元素的文本?

感谢您的帮助!

【问题讨论】:

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


    【解决方案1】:

    一旦我们深入研究它,实际上并没有那么奇怪的行为。使用root.element.subelement.... 并没有像您想象的那样执行。我们可以使用etree打印出xml树的状态并检查结构。

    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>
    

    这看起来是正确的。那么当我们调用objroot.child4 = True 时会发生什么? API 允许您执行此操作,但它不只是添加文本。相反,它将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"
    

    它实际上在child4 下创建每个子元素,然后即时设置值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-06
      • 1970-01-01
      相关资源
      最近更新 更多