提问人:TheDataPanda 提问时间:6/29/2023 最后编辑:larsksTheDataPanda 更新时间:6/29/2023 访问量:28
使用 Python 对 XML 进行排序时忽略某些节点
Ignore certain nodes when sorting XML with Python
问:
我有一个 XML。粗略地说,有根节点。然后,在该级别之下,您有各种节点,其中一些节点带有“系统”标签。在每个“系统”节点中,还有各种其他节点,其中一些称为“扩展”。最后,在“Extents”中,有各种节点,其中一个是“LineSize”,其“Value”属性设置为一个数字。
我基本上是在尝试对每个“系统”节点进行排序,以便所有“范围”都按“LineSize”排序。我想忽略“系统”中的所有其他节点,而只是按顺序对“范围”进行排序。理想情况下,将其他节点保留在原处(它们总是在所有“范围”之前或之后)。
这是我的代码:
import xml.etree.ElementTree as ET
my_tree = ET.parse('test.xml')
root = my_tree.getroot()
for node in root:
if node.tag == "System":
for child_node in node:
child_node[:] = sorted(child_node, key=lambda segment_node: int(segment_node.find("LineSize").attrib["Value"]), reverse=True)
my_tree.write('test_ordered.xml')
现在的问题是它不会为“Extents”以外的元素找到“LineSize”,因此会抛出错误。
XML 与此类似。运行工作代码后的唯一变化是 id = 1 的扩展将排在 id = 2 的扩展之后,因为我将按降序排序(两者都仍在 name = aa 的系统下。
图形节点将停留在同一个位置,或者至少不会成为排序的一部分。
<root>
<system name = "aa">
<graphics>
</graphics>
<extents id = "1" name = "aa">
<LineSize Value = "10" />
</extents>
<extents id = "2" name = "aa">
<LineSize Value = "40" />
</extents>
</system>
<system name = "bb">
<extents id = "3" name = "bb">
<LineSize Value = "90" />
</extents>
<extents id = "4" name = "bb">
<LineSize Value = "20" />
</extents>
<random1>
</random1>
</system>
<random>
</random>
</root>
答:
0赞
larsks
6/29/2023
#1
下面是一个可能的解决方案:
import xml.etree.ElementTree as ET
my_tree = ET.parse("test.xml")
root = my_tree.getroot()
for node in root:
if node.tag == "system":
child_nodes = sorted(
node,
key=lambda node: int(node.find("LineSize").get("Value", 0))
if node.tag == "extents"
else 0,
)
for child_node in reversed(child_nodes):
node.remove(child_node)
node.insert(0, child_node)
my_tree.write("test_ordered.xml")
我们获取每个元素的子节点列表,然后对列表进行排序,放置不在列表顶部的元素。对于每个子节点,我们首先将其从之前占据的任何位置移除,然后重新插入。<system>
extents.LineSize
<extents>
对示例数据运行,这将生成:
<root>
<system name="aa">
<graphics></graphics>
<extents id="1" name="aa">
<LineSize Value="10" />
</extents>
<extents id="2" name="aa">
<LineSize Value="40" />
</extents>
</system>
<system name="bb">
<random1></random1>
<extents id="4" name="bb">
<LineSize Value="20" />
</extents>
<extents id="3" name="bb">
<LineSize Value="90" />
</extents>
</system>
<random></random>
</root>
评论
0赞
TheDataPanda
6/29/2023
谢谢。我尝试更新它,以便它会以相反的方式排序(最高优先)。但是,似乎会导致一些问题。其中一个扩展数据块最终位于系统节点之外。
0赞
TheDataPanda
6/29/2023
尽管这可能是 VS Code 格式化的问题。当我有 reverse = True 时,它看起来可能正在工作
0赞
larsks
6/29/2023
如果你想要最高,就用而不是(这实际上是我首先测试的,但我假设你首先想要最低,所以我添加了调用)。这会将非节点放在底部而不是顶部,但如果这是一个问题,您可以在调用中使用大值而不是默认值。for child node in child_nodes
for child node in reversed(child_nodes)
reversed()
<extents>
0
sorted()
评论
"
<System>