问题描述
我有一个带有多个带有嵌套子项的父项的XML文件,我想添加一个新的“ order”标签来指示他们的订单。
此刻我有类似的东西
<root>
<level id='FRUITS'>
<level id='APPLE'>
<heading>APPLE HEADER </heading>
<level id='APPLE_ONE'>
<file fileName='APPLE_ONE_I' />
<heading>This is Apple One I.</heading>
<file fileName='APPLE_ONE_II' />
<heading>This is Apple One II.</heading>
</level>
<level id='APPLE_TWO'>
<file fileName='APPLE_TWO_II' />
<heading>This is Apple One I.</heading>
</level>
</level>
<level id='ORANGE'>
<heading>ORANGE HEADER</heading>
<level id='ORANGE_ONE'>
<file fileName='ORANGE_ONE_I' />
<heading>This is Orange One I.</heading>
</level>
</level>
</level>
</root>
我需要为ID的顺序添加一个指示符,而不是文件的指示符。这样看起来就像
<root>
<level id='FRUITS' order='1'>
<level id='APPLE' order='1'>
<heading>APPLE HEADER</heading>
<level id='APPLE_ONE' order='1'>
<file fileName='APPLE_ONE_I' />
<heading>This is Apple One I.</heading>
<file fileName='APPLE_ONE_II' />
<heading>This is Apple One II.</heading>
</level>
<level id='APPLE_TWO' order='2'>
<file fileName='APPLE_TWO_II' />
<heading>This is Apple One I.</heading>
</level>
</level>
<level id='ORANGE' order='2'>
<heading>ORANGE HEADER</heading>
<level id='ORANGE_ONE' order='1'>
<file fileName='ORANGE_ONE_I' />
<heading>This is Orange One I.</heading>
</level>
</level>
</level>
</root>
解决方法
一种方法是在lxml中使用xpath()来获取前一个同级level
的数量,以确定“ order”的值...
from lxml import etree
xml = """<root>
<level id='FRUITS'>
<level id='APPLE'>
<heading>APPLE HEADER </heading>
<level id='APPLE_ONE'>
<file fileName='APPLE_ONE_I' />
<heading>This is Apple One I.</heading>
<file fileName='APPLE_ONE_II' />
<heading>This is Apple One II.</heading>
</level>
<level id='APPLE_TWO'>
<file fileName='APPLE_TWO_II' />
<heading>This is Apple One I.</heading>
</level>
</level>
<level id='ORANGE'>
<heading>ORANGE HEADER</heading>
<level id='ORANGE_ONE'>
<file fileName='ORANGE_ONE_I' />
<heading>This is Orange One I.</heading>
</level>
</level>
</level>
</root>
"""
tree = etree.fromstring(xml)
for level in tree.xpath(".//level"):
level.set("order",str(len(level.xpath("preceding-sibling::level")) + 1))
print(etree.tostring(tree).decode())
打印输出...
<root>
<level id="FRUITS" order="1">
<level id="APPLE" order="1">
<heading>APPLE HEADER </heading>
<level id="APPLE_ONE" order="1">
<file fileName="APPLE_ONE_I"/>
<heading>This is Apple One I.</heading>
<file fileName="APPLE_ONE_II"/>
<heading>This is Apple One II.</heading>
</level>
<level id="APPLE_TWO" order="2">
<file fileName="APPLE_TWO_II"/>
<heading>This is Apple One I.</heading>
</level>
</level>
<level id="ORANGE" order="2">
<heading>ORANGE HEADER</heading>
<level id="ORANGE_ONE" order="1">
<file fileName="ORANGE_ONE_I"/>
<heading>This is Orange One I.</heading>
</level>
</level>
</level>
</root>