Python 将点符号字符串转换为对象以访问lxml对象

Python 将点符号字符串转换为对象以访问lxml对象,python,lxml,lxml.objectify,Python,Lxml,Lxml.objectify,我正在尝试使用lxml objectify使用对象表示法更新xml <xml> <fruit> <citrus> <lemon /> </citrus> </fruit> </xml> 我想传递一个字符串,比如'fruit.citrus',因为我不能传递对象fruit.citrus 如何在Python ie中实现这一点?如何在更新函数中执行代码'root.fruit.

我正在尝试使用lxml objectify使用对象表示法更新xml

<xml>
  <fruit>
    <citrus>
        <lemon />
    </citrus>
  </fruit>  
</xml>
我想传递一个字符串,比如'fruit.citrus',因为我不能传递对象fruit.citrus

如何在Python ie中实现这一点?如何在更新函数中执行代码'root.fruit.citrus='orange'。如何将字符串转换为对象?

请尝试以下解决方案:

import lxml.objectify, lxml.etree

xml = '<xml>  <fruit>    <citrus>        <lemon />    </citrus>  </fruit> </xml>'

root = lxml.objectify.fromstring(xml)

print("Before:")
print(lxml.etree.tostring(root))


def update(path, value):
    parent = None
    lst = path.split('.')
    while lst:
        ele = lst.pop(0)
        parent = getattr(root, ele) if parent is None else getattr(parent, ele)
    lxml.etree.SubElement(parent, value)


update('fruit.citrus', 'orange')

print("After:")
print(lxml.etree.tostring(root))
导入lxml.objectify,lxml.etree
xml=“”
root=lxml.objectify.fromstring(xml)
打印(“之前:”)
打印(lxml.etree.tostring(根))
def更新(路径、值):
父项=无
lst=path.split('.'))
而lst:
ele=第一个pop(0)
父项=getattr(根,ele),如果父项不是其他getattr(父项,ele)
lxml.etree.SubElement(父元素,值)
更新('fruit.citrus','orange')
打印(“之后:”)
打印(lxml.etree.tostring(根))
输出:

Before:
b'<xml><fruit><citrus><lemon/></citrus></fruit></xml>'
After:
b'<xml><fruit><citrus><lemon/><orange/></citrus></fruit></xml>'
之前:
b“
之后:
b“

如果您坚持使用
objectify
,您可能不喜欢这样,但我认为使用
lxml
这是一个非常干净的解决方案:

from lxml import etree

doc = etree.fromstring("""<xml>
  <fruit>
    <citrus>
        <lemon />
    </citrus>
  </fruit>  
</xml>""")


def update(root, path, item):
    elems = root.xpath(path)
    for elem in elems:
        elem.append(etree.Element(item))


update(doc, 'fruit/citrus', 'orange')
print(etree.tostring(doc).decode())
从lxml导入etree
doc=etree.fromstring(“”)
""")
def更新(根目录、路径、项):
elems=root.xpath(路径)
对于元素中的元素:
元素附加(etree.Element(item))
更新(文件‘水果/柑橘’、‘橘子’)
打印(etree.tostring(doc.decode())

上述答案部分正确。它没有处理索引的能力。下面的代码使用ObjectPath()处理所有情况


谢谢你的回答。我同意它要干净得多,但我必须使用点符号,因为我已经为它编写了代码,并且我正在通过替换eval来修改库。有没有理由不将这一行添加到
update()
,而仍然使用它
path=path.replace('.','/')
请您添加一个关于如何添加索引的解决方案。例如更新('fruit.citrus[1],'orange'),谢谢
from lxml import etree

doc = etree.fromstring("""<xml>
  <fruit>
    <citrus>
        <lemon />
    </citrus>
  </fruit>  
</xml>""")


def update(root, path, item):
    elems = root.xpath(path)
    for elem in elems:
        elem.append(etree.Element(item))


update(doc, 'fruit/citrus', 'orange')
print(etree.tostring(doc).decode())
import lxml.objectify, lxml.etree

from robot.api.deco import keyword

class ConfigXML(object):
    def get_xml(self, filename):
        self.root = lxml.objectify.fromstring(open(filename).read())

    def add_attribute(self, path, **kwargs):
        path_obj = lxml.objectify.ObjectPath(path)
        for key in kwargs:
            path_obj.find(self.root).set(key, kwargs[key])

    def add_value(self, path, value):
        path_obj = lxml.objectify.ObjectPath(path)
        path_obj.setattr(self.root, value)

    def add_tag(self, path, tag):
        path_obj = lxml.objectify.ObjectPath(path)
        lxml.objectify.SubElement(path_obj.find(self.root), tag)

    def generate_xml(self):
        lxml.objectify.deannotate(self.root, cleanup_namespaces=True, xsi_nil=True)
        return lxml.etree.tostring(self.root).decode('utf-8')