问题描述
我有以下示例XML文件,我想在<item>DEV</item>
之后添加元素<item>Production</item>
之前(Sample.xml)
<resource xmlns:ns0="http://schemas.android.com/apk" xmlns:ns1="http://schemas.android">
<string-array name="selectable_environment" ns1:ignore="InconsistenArray">
<item>QA</item>
<item>SIT</item>
<item>Staging</item>
<item>Production</item>
<item>RQA</item>
<item>PTE</item>
</string-array>
<resource>
预期输出(Output.xml)
<resource xmlns:ns0="http://schemas.android.com/apk" xmlns:ns1="http://schemas.android">
<string-array name="selectable_environment" ns1:ignore="InconsistenArray">
<item>QA</item>
<item>SIT</item>
<item>Staging</item>
<item>Production</item>
<item>DEV</item>
<item>RQA</item>
<item>PTE</item>
</string-array>
<resource>
这是我的示例代码
import xml.etree.ElementTree as ET
mytree = ET.parse("Sample.xml")
root = mytree.getroot()
for child in root.iter('item'):
if child.text == "Production":
new = ET.SubElement(child,'item')
new.text = "DEV"
mytee.write("Output.xml")
我得到的结果是
<resource xmlns:ns0="http://schemas.android.com/apk" xmlns:ns1="http://schemas.android">
<string-array name="selectable_environment" ns1:ignore="InconsistenArray">
<item>QA</item>
<item>SIT</item>
<item>Staging</item>
<item>Production<item>DEV</item></item>
<item>DEV</item>
<item>RQA</item>
<item>PTE</item>
</string-array>
<resource>
解决方法
要解决您的问题,您可以使用文本“生产”来收集节点的父级。您还需要使节点的索引带有文本“ Production”:您可以使用函数enumerate()
来获得它。您可以这样编码:
import xml.etree.ElementTree as ET
mytree = ET.parse("Sample.xml")
root = mytree.getroot()
for child in root.iter():
for i,elt in enumerate(child.getchildren()):
if elt.text == "Production":
new = ET.Element('item')
new.text = "DEV"
child.insert(i+1,new)
mytree.write("Output.xml")
,
能否请您分享一些有关如何使用lxml添加新元素的示例。我尝试使用@ Pierre-Loic shared解决方案,它可以正常工作,但是在添加新Element之后,它不会创建新行。
这是在lxml中使用addnext()
方法的核心示例...
from lxml import etree
tree = etree.parse("input.xml")
try:
target_elem = tree.xpath("./string-array/item[.='Production']")[0]
new_elem = etree.fromstring("<item>DEV</item>") # Could also construct a new Element and set .text.
target_elem.addnext(new_elem)
except IndexError:
print("Unable to find target element.")
tree.write("output.xml")
但是,正如您将看到的,这还会在同级的同一行上输出新的item
...
<resource xmlns:ns0="http://schemas.android.com/apk" xmlns:ns1="http://schemas.android">
<string-array name="selectable_environment" ns1:ignore="InconsistenArray">
<item>QA</item>
<item>SIT</item>
<item>Staging</item>
<item>Production</item><item>DEV</item>
<item>RQA</item>
<item>PTE</item>
</string-array>
</resource>
这纯粹是格式化,但是如果您想“重置”漂亮的打印,我建议将树序列化为字符串,然后使用XMLParser解析该字符串以去除所有空白,然后将新的漂亮打印的树写入一个文件...
from lxml import etree
tree = etree.parse("input.xml")
try:
target_elem = tree.xpath("./string-array/item[.='Production']")[0]
new_elem = etree.fromstring("<item>DEV</item>") # Could also construct a new Element and set .text.
target_elem.addnext(new_elem)
except IndexError:
print("Unable to find target element.")
# "Reset" pretty printing and write to file.
parser = etree.XMLParser(remove_blank_text=True)
etree.ElementTree(etree.fromstring(etree.tostring(tree),parser=parser)).write("output.xml",pretty_print=True)
输出...
<resource xmlns:ns0="http://schemas.android.com/apk" xmlns:ns1="http://schemas.android">
<string-array name="selectable_environment" ns1:ignore="InconsistenArray">
<item>QA</item>
<item>SIT</item>
<item>Staging</item>
<item>Production</item>
<item>DEV</item>
<item>RQA</item>
<item>PTE</item>
</string-array>
</resource>
我们可以在元素中添加缩进吗?要求是
<item>...</item>
带有4个缩进。现在我看到所有元素只有2个。原始文件有4个,但是此脚本在添加了新的Element之后将缩进更改为2。
如果您使用的是lxml 4.5或更高版本,则可以使用indent() function ...
from lxml import etree
tree = etree.parse("input.xml")
try:
target_elem = tree.xpath("./string-array/item[.='Production']")[0]
new_elem = etree.fromstring("<item>DEV</item>") # Could also construct a new Element and set .text.
target_elem.addnext(new_elem)
except IndexError:
print("Unable to find target element.")
# "Reset" pretty printing.
parser = etree.XMLParser(remove_blank_text=True)
new_tree = etree.ElementTree(etree.fromstring(etree.tostring(tree),parser=parser))
# Indent 4 spaces instead of the default 2.
etree.indent(new_tree,space=" ")
# Write to file.
new_tree.write("output.xml",pretty_print=True)
输出...
<resource xmlns:ns0="http://schemas.android.com/apk" xmlns:ns1="http://schemas.android">
<string-array name="selectable_environment" ns1:ignore="InconsistenArray">
<item>QA</item>
<item>SIT</item>
<item>Staging</item>
<item>Production</item>
<item>DEV</item>
<item>RQA</item>
<item>PTE</item>
</string-array>
</resource>