如何用Python ElementTree对嵌套XML的line元素按reqdat降序排序?
使用Python ElementTree对XML中元素按降序排序
需要处理指定结构的XML文档,将<header>节点下的所有<line>元素,按照<reqdat>字段的日期值从新到旧(降序)排序,排序后的XML将用于打印输出。
示例输入XML
<doc> <header> <ordernum>1234</ordernum> <customer>1</customer> <line> <lineno>1</lineno> <reqdat>2024-01-01</reqdat> </line> <line> <lineno>2</lineno> <reqdat>2024-03-01</reqdat> </line> <line> <lineno>3</lineno> <reqdat>2024-02-01</reqdat> </line> </header> </doc>
期望输出XML
<doc> <header> <ordernum>1234</ordernum> <customer>1</customer> <line> <lineno>2</lineno> <reqdat>2024-03-01</reqdat> </line> <line> <lineno>3</lineno> <reqdat>2024-02-01</reqdat> </line> <line> <lineno>1</lineno> <reqdat>2024-01-01</reqdat> </line> </header> </doc>
解决方案代码
import xml.etree.ElementTree as ET # 示例XML内容(也可通过ET.parse('input.xml')读取本地文件) xml_content = """ <doc> <header> <ordernum>1234</ordernum> <customer>1</customer> <line> <lineno>1</lineno> <reqdat>2024-01-01</reqdat> </line> <line> <lineno>2</lineno> <reqdat>2024-03-01</reqdat> </line> <line> <lineno>3</lineno> <reqdat>2024-02-01</reqdat> </line> </header> </doc> """ # 解析XML root = ET.fromstring(xml_content) header_node = root.find('header') # 获取所有<line>元素并排序 line_elements = header_node.findall('line') # 按<reqdat>文本降序排序(YYYY-MM-DD格式可直接字符串比较) sorted_lines = sorted(line_elements, key=lambda x: x.find('reqdat').text, reverse=True) # 移除原有的<line>元素 for line in line_elements: header_node.remove(line) # 将排序后的元素添加回<header> for line in sorted_lines: header_node.append(line) # 格式化输出(Python3.9+支持ET.indent添加缩进) ET.indent(root, space=" ") print(ET.tostring(root, encoding='utf-8', xml_declaration=True).decode('utf-8'))
关键步骤说明
- XML解析:使用
ET.fromstring()解析字符串内容,若处理本地文件可替换为ET.parse()。 - 节点定位:通过
find()和findall()精准获取目标节点。 - 排序逻辑:利用
sorted()函数,以<reqdat>的文本内容为排序依据,reverse=True实现降序;由于日期为YYYY-MM-DD格式,直接字符串比较即可保证排序正确性。 - 节点更新:必须先移除原有
<line>元素,再添加排序后的元素,避免节点重复或顺序未生效。 - 格式化输出:
ET.indent()用于添加缩进,让输出XML结构更清晰,符合打印需求。
内容的提问来源于stack exchange,提问作者anterys
相关产品推荐
相关产品推荐

