使用 lxml.objectify 替换节点文本,同时保留属性

问题描述 投票:0回答:2

像这样使用

lxml.objectify

from lxml import objectify

o = objectify.fromstring("<a><b atr='someatr'>oldtext</b></a>")

o.b = 'newtext'

导致

<a><b>newtext</b></a>
,失去节点属性。看起来像是直接将元素替换为新创建的元素,而不是简单地替换元素的文本。

如果我尝试使用

o.b.text = 'newtext'
,它会告诉我
attribute 'text' of 'StringElement' objects is not writable

有没有一种方法可以在 objectify 中做到这一点,而不必将其拆分为不同的元素并涉及 etree?我只是想替换内部文本,同时保留节点的其余部分。我觉得我在这里缺少一些简单的东西。

python xml lxml
2个回答
10
投票
>>> type(o.b)
<type 'lxml.objectify.StringElement'>

您正在用纯字符串替换元素。您需要将其替换为新的字符串元素。

>>> o.b = objectify.E.b('newtext', atr='someatr')

由于某种原因你不能这样做:

>>> o.b.text = 'newtext'

但是,这似乎有效:

>>> o.b._setText('newtext')

0
投票

这条线似乎有效

    publisher.getparent().publisher = 'Nerd Publishers'

试试这个

    # -*- coding: utf-8 -*-
""""""

from lxml import etree
from lxml.etree import ElementTree as ElT
from lxml import objectify

root = objectify.Element('Document')

# Children of root
filedesc = objectify.SubElement(root, 'filedesc')
title = objectify.SubElement(filedesc, 'title')
publicationstmt = objectify.SubElement(filedesc, 'publicationstmt')
publisher = objectify.SubElement(publicationstmt, 'publisher')

publisher.getparent().publisher = 'Nerd Publishers'

# Remove lxml annotation
objectify.deannotate(root, cleanup_namespaces=True)

etree.indent(root)
tree = ElT(root)

print(etree.tostring(tree, encoding='utf-8').decode())

此代码产生

<Document>
  <filedesc>
    <title/>
    <publicationstmt>
      <publisher>Nerd Publishers</publisher>
    </publicationstmt>
  </filedesc>
</Document>
© www.soinside.com 2019 - 2024. All rights reserved.