我正在寻找以下python的解决方案。 以下是我当前的 xml 文件格式。
<step_1>abc</step_1>
<step_2>efg</step_2>
<step_3>hij</step_3>
<step_4>klm</step_4>
我想在第一个和最后一个之间添加/删除一个标签,并按顺序维护标签的命名。例如:如果我删除<step_2>efg</step_2>
那么结果应如下所示
<step_1>abc</step_1>
<step_2>hij</step_2>
<step_3>klm</step_3>
有什么解决方案吗? 提前谢谢你。
我检查了XML元素的标签属性可以修改, 至少使用LXML。
我的解决方案基于lxml的另一个原因是它包含xpath方法,这是这里需要的。
首先,假设您已经添加或删除了一些step_...元素 在你的源树中,还有具有其他名称的元素,现在 整棵树包含:
<main>
<xx>
<other>a1</other>
<step_1>abc</step_1>
<step_3>hij</step_3>
<other>a2</other>
<step_4>klm</step_4>
<step_6>xyz</step_6>
</xx>
<yy>
<step_1>abc_2</step_1>
<step_7>xyz_2</step_7>
<step_2>efg_2</step_2>
<other>a3</other>
<step_4>klm_2</step_4>
</yy>
</main>
我从一个文件中阅读了上述内容:
from lxml import etree as et
parser = et.XMLParser(remove_blank_text=True)
tree = et.parse('Input.xml', parser)
root = tree.getroot()
那么这个想法是:
- 查找每个包含至少一个step_...元素的"父"元素。
- 循环遍历其子项,其名称从步骤开始。
- 将其名称(标记(更改为step_+ 连续数字。
使用测试打印输出执行此操作的代码是:
for el in root.xpath(".//*[starts-with(name(), 'step')]/.."):
tg = el.tag
print(f'Parent: {tg:7}')
i = 0
for el2 in el.xpath("*[starts-with(name(), 'step')]"):
i += 1
tg2 = el2.tag
tt = el2.text
if tt is None: tt = ''
newName = f'step_{i}'
print(f' Child {i}: {tg2:7} {tt:8} -> {newName}')
el2.tag = newName
它打印:
Parent: xx
Child 1: step_1 abc -> step_1
Child 2: step_3 hij -> step_2
Child 3: step_4 klm -> step_3
Child 4: step_6 xyz -> step_4
Parent: yy
Child 1: step_1 abc_2 -> step_1
Child 2: step_7 xyz_2 -> step_2
Child 3: step_2 efg_2 -> step_3
Child 4: step_4 klm_2 -> step_4
现在打印内容时:
print(et.tostring(root, encoding='unicode', pretty_print=True))
结果是:
<main>
<xx>
<other>a1</other>
<step_1>abc</step_1>
<step_2>hij</step_2>
<other>a2</other>
<step_3>klm</step_3>
<step_4>xyz</step_4>
</xx>
<yy>
<step_1>abc_2</step_1>
<step_2>xyz_2</step_2>
<step_3>efg_2</step_3>
<other>a3</other>
<step_4>klm_2</step_4>
</yy>
</main>
如您所见:
- step_...元素已被"重新计算",从其父元素中的1开始。
- 所有其他元素都保持其位置和内容。