将点符号字符串转换为对象以访问 lxml 对象 python
Convert a dot notation string to object to access lxml objects python
我正在尝试使用 lxml 对象化更新 xml 使用对象表示法。
<xml>
<fruit>
<citrus>
<lemon />
</citrus>
</fruit>
</xml>
我正在尝试使用 lxml objectify 添加另一种叫做芒果的水果
root = lxml.objectify.fromstring(xml_string)
root.fruit.citrus = 'orange'
def update(path, value):
// code
update('fruit.citrus', 'orange')
我想传递一个像 'fruit.citrus' 这样的字符串,因为我不能传递一个对象 fruit.citrus。
如何在 Python 中实现这一点,即如何在更新函数中执行代码 '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))
输出:
Before:
b'<xml><fruit><citrus><lemon/></citrus></fruit></xml>'
After:
b'<xml><fruit><citrus><lemon/><orange/></citrus></fruit></xml>'
如果您坚持使用 objectify
,您可能不喜欢这个,但我认为这是一个使用 lxml
etree
:
的非常干净的解决方案
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())
以上回答部分正确。它没有处理索引的能力。下面的代码处理所有带有 ObjectPath (https://lxml.de/objectify.html).
的情况
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')
我正在尝试使用 lxml 对象化更新 xml 使用对象表示法。
<xml>
<fruit>
<citrus>
<lemon />
</citrus>
</fruit>
</xml>
我正在尝试使用 lxml objectify 添加另一种叫做芒果的水果
root = lxml.objectify.fromstring(xml_string)
root.fruit.citrus = 'orange'
def update(path, value):
// code
update('fruit.citrus', 'orange')
我想传递一个像 'fruit.citrus' 这样的字符串,因为我不能传递一个对象 fruit.citrus。
如何在 Python 中实现这一点,即如何在更新函数中执行代码 '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))
输出:
Before:
b'<xml><fruit><citrus><lemon/></citrus></fruit></xml>'
After:
b'<xml><fruit><citrus><lemon/><orange/></citrus></fruit></xml>'
如果您坚持使用 objectify
,您可能不喜欢这个,但我认为这是一个使用 lxml
etree
:
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())
以上回答部分正确。它没有处理索引的能力。下面的代码处理所有带有 ObjectPath (https://lxml.de/objectify.html).
的情况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')