首页 > 解决方案 > 是否可以使用 python 按字母顺序对 xml 属性值进行排序?

问题描述

我有一个类似的 xml 文件,我想在其中按字母顺序对 a 标签的属性值进行排序。

<x name = something>
  <a name = BBB> </a>
  <a name = AAA> </a>
  <a name = CCC> </a>
</x>
<x name = random>
  <a name = CCC> </a>
  <a name = BBB> </a>
  <a name = AAA> </a>
</x>

我希望输出 xml 文件为:

<x name = something>
  <a name = AAA> </a>
  <a name = BBB> </a>
  <a name = CCC> </a>
</x>
<x name = random>
  <a name = AAA> </a>
  <a name = BBB> </a>
  <a name = CCC> </a>
</x>

标签: pythonxmlsorting

解决方案


像这样的东西也许是你正在寻找的东西。

我已经在源代码中嵌入了一个示例文档,但是您可以从磁盘或任何您想要的地方加载 XML。

这个想法是有一个递归函数,它接受一个任意条件(谓词)函数和一个sort键函数;这样你就可以选择哪些树应该被重新排序——或者如果你只想重新排序所有东西,它可以是一个总是返回 True 的函数。

import xml.etree.ElementTree as etree


def sort_tree(node, sort_cond, sort_key):
    # If this node matches the condition,
    if sort_cond(node):
        # ... sort the children and reapply into the node.
        node[:] = sorted(node, key=sort_key)

    # Recurse down the tree.
    for child in node:
        sort_tree(child, sort_cond, sort_key)


tree = etree.XML("""
<document>
    <x name="xxsomething">
      <a name="BBB">some thing bbb</a>
      <a name="AAA">aaa some thing</a>
      <a name="CCC">some ccc thing</a>
    </x>
    <x name="aarandom">
      <a name="ZXY">asdf</a>
      <a name="888">ghkj</a>
      <a name="uuu">tyiu</a>
    </x>
</document>
""")
sort_tree(
    tree,
    sort_cond=lambda node: all(child.tag == "a" for child in node),
    sort_key=lambda node: node.get("name"),
)
print(etree.tostring(tree, encoding='unicode'))

输出:

<document>
    <x name="xxsomething">
      <a name="AAA">aaa some thing</a>
      <a name="BBB">some thing bbb</a>
      <a name="CCC">some ccc thing</a>
    </x>
    <x name="aarandom">
      <a name="888">ghkj</a>
      <a name="ZXY">asdf</a>
      <a name="uuu">tyiu</a>
    </x>
</document>

(请注意,x即使标签的“名称”顺序错误,标签也不会重新排序,因为该cond函数仅适用于节点的所有子节点都是a节点的情况。)


推荐阅读