按子元素Python排序XML标签

bzz*_*omp 1 python lxml elementtree python-2.7

我有许多带有孩子“名称”的“根”标签。我想对“根”块进行排序,并按“名称”元素按字母顺序排序。尝试过lxml / etree / minidom,但是无法正常工作...我无法获取它来解析标记内的值,然后对父根标记进行排序。

<?xml version='1.0' encoding='UTF-8'?>
  <roots>
    <root>
      <path>//1.1.1.100/Alex</path>
      <name>Alex Space</name>
    </root>
    <root>
      <path>//1.1.1.101/Steve</path>
      <name>Steve Space</name>
    </root>
    <root>
      <path>//1.1.1.150/Bethany</path>
      <name>Bethanys</name>
    </root>
</roots>
Run Code Online (Sandbox Code Playgroud)

这是我尝试过的:

import xml.etree.ElementTree as ET

    def sortchildrenby(parent, child):
        parent[:] = sorted(parent, key=lambda child: child)


tree = ET.parse('data.xml')
root = tree.getroot()

sortchildrenby(root, 'name')
for child in root:
    sortchildrenby(child, 'name')


tree.write('output.xml')
Run Code Online (Sandbox Code Playgroud)

Pad*_*ham 5

如果要首先放置名称节点:

x = """
  <roots>
    <root>
      <path>//1.1.1.100/Alex</path>
      <name>Alex Space</name>
    </root>
    <root>
      <path>//1.1.1.101/Steve</path>
          <name>Bethanys</name>
    </root>
    <root>
      <path>//1.1.1.150/Bethany</path>
        <name>Steve Space</name>
    </root>
</roots>"""

import lxml.etree as et
tree = et.fromstring(x)

for r in tree.iter("root"):
    r[:] = sorted(r, key=lambda ch: -(ch.tag == "name"))

print(et.tostring(tree).decode("utf-8"))
Run Code Online (Sandbox Code Playgroud)

这会给你:

<roots>
    <root>
      <name>Alex Space</name>
    <path>//1.1.1.100/Alex</path>
      </root>
    <root>
      <name>Bethanys</name>
    <path>//1.1.1.101/Steve</path>
          </root>
    <root>
      <name>Steve Space</name>
    <path>//1.1.1.150/Bethany</path>
        </root>
</roots>
Run Code Online (Sandbox Code Playgroud)

但是,如果您只想先添加它们,则无需排序,只需删除名称并将其重新插入索引0中即可:

import lxml.etree as et
tree = et.fromstring(x)

for r in tree.iter("root"):
    ch = r.find("name")
    r.remove(ch)
    r.insert(0, ch)

print(et.tostring(tree).decode("utf-8"))
Run Code Online (Sandbox Code Playgroud)

如果节点实际上不是有序,并要重新排列的按字母顺序排列节点:

x = """
  <roots>
    <root>
      <path>//1.1.1.100/Alex</path>
      <name>Alex Space</name>
    </root>
    <root>
      <path>//1.1.1.101/Steve</path>
         <name>Steve Space</name>
    </root>
    <root>
       <path>//1.1.1.150/Bethany</path>
       <name>Bethanys</name>
    </root>
</roots>"""
import lxml.etree as et
tree = et.fromstring(x)

tree[:] = sorted(tree, key=lambda ch: ch.xpath("name/text()"))

print(et.tostring(tree).decode("utf-8"))
Run Code Online (Sandbox Code Playgroud)

这会给你:

 <roots>
    <root>
      <path>//1.1.1.100/Alex</path>
      <name>Alex Space</name>
    </root>
    <root>
       <path>//1.1.1.150/Bethany</path>
       <name>Bethanys</name>
    </root>
    <root>
      <path>//1.1.1.101/Steve</path>
         <name>Steve Space</name>
    </root>
</roots>
Run Code Online (Sandbox Code Playgroud)

您还可以与前两种方法之一结合使用,还可以重新排列将名称放在首位的根节点