按 child 个元素 Python 对 XML 个标签进行排序

Sorting XML tags by child elements Python

我有很多 'root' 个标签 children 'name'。我想对 'root' 块进行排序,按 'name' 元素的字母顺序排列。已经尝试过 lxml / etree / minidom 但无法正常工作...... 我无法让它解析标签内的值,然后对 parent 根标签进行排序。

<?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>

这是我尝试过的:

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')

试试这个:

import xml.etree.ElementTree as ET


xml="<?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>"
oldxml = ET.fromstring(xml)

names = []
for rootobj in oldxml.findall('root'):
    names.append(rootobj.find('name').text)

newxml = ET.Element('roots')
for name in sorted(names):
    for rootobj in oldxml.findall('root'):
        if name == rootobj.find('name').text:
            newxml.append(rootobj)
ET.dump(oldxml)
ET.dump(newxml)

我正在读取变量并将其转储到屏幕上。

您可以更改它从文件中读取并将其转储到您需要的文件中。

如果要将 name 个节点放在第一位:

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"))

哪个会给你:

<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>

但是如果你只想先添加它们,则不需要排序,你可以删除名称并将其重新插入到索引 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"))

如果节点实际上没有按排序顺序排列并且您想按字母顺序重新排列 roots 节点:

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"))

哪个会给你:

 <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>

您还可以结合前两种方法中的任何一种,两种方法还可以重新排列 root 节点,将名称放在首位。