首页 > 解决方案 > Python XML 按属性/子项排序

问题描述

我正在使用 Python (2.7/3.8) 并处理一些比较复杂的 XML。XML 的顺序可以不同,我正在构建一个作为排序规则的函数(查看节点属性,然后查看子节点)。

我查看了一些不同的相关问题,但都不适用于我的场景:

我可以使用 进行排序key=lambda child: child.tag,但是我通常希望使用属性而不是标签名称。

在最基本的情况下,我希望能够按属性名称排序,检查 ['id', 'label', 'value'] 中的任何一个是否作为属性存在,并将其用作键。无论如何,我似乎无法弄清楚为什么 child.tag 可以排序,但 child.get('id') 不能。

import xml.etree.ElementTree as etree
    
input = '''
    <root>
        <node id="7"></node>
        <node id="10"></node>
        <node id="5"></node>
    </root>
'''

root = etree.fromstring(input)

root[:] = sorted(root, key=lambda child: child.get('id'))

xmlstr = etree.tostring(root, encoding="utf-8", method="xml")
print(xmlstr.decode("utf-8"))

返回:

<root>
    <node id="7" />
    <node id="5" />
    <node id="10" />
</root>

预期的:

<root>
    <node id="5" />
    <node id="7" />
    <node id="10" />
</root>

编辑

正如所提到的,用 int() 包装 child.get('id') 确实解决了这个问题,但是代码必须另外适用于同时具有字母 + 数字的输入,例如 id="node1"、"node15"、等等

例如:

<root>
    <node id="node10" />
    <node id="node7" />
    <node id="node5" />
</root>

预期的:

<root>
    <node id="node5" />
    <node id="node7" />
    <node id="node10" />
</root>

标签: pythonxmlsortingelementtree

解决方案


您应该将id值转换为int并且您可以使用正则表达式从中提取didgitid

import re


root[:] = sorted(root, key=lambda child: int(re.search('\d+', child.get('id')).group()))

xmlstr = etree.tostring(root, encoding="utf-8", method="xml")
print(xmlstr.decode("utf-8"))

输出:

<root>
    <node id="node5" />
    <node id="node7" />
    <node id="node10" />
</root>

推荐阅读