Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python XML按属性/子级排序_Python_Xml_Sorting_Elementtree - Fatal编程技术网

Python XML按属性/子级排序

Python XML按属性/子级排序,python,xml,sorting,elementtree,Python,Xml,Sorting,Elementtree,我正在使用Python(2.7/3.8)并处理一些比较复杂的XML。XML的顺序可能会有所不同,我正在构建一个函数作为排序规则(查看节点属性,然后查看节点子节点) 我已经看了一些不同的相关问题,但它们都不适用于我的场景: 我可以使用key=lambda child:child.tag进行排序,但是我通常希望使用属性而不是标记名 在最基本的情况下,我希望能够按属性名排序,检查['id'、'label'、'value']中是否有任何属性存在,并将其用作键。不管怎样,我似乎不明白为什么chil

我正在使用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"))
将xml.etree.ElementTree导入为etree
输入=“”
'''
root=etree.fromstring(输入)
root[:]=sorted(root,key=lambda-child:child.get('id'))
xmlstr=etree.tostring(root,encoding=“utf-8”,method=“xml”)
打印(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>
<root>
    <node id="node5" />
    <node id="node7" />
    <node id="node10" />
</root>

编辑

正如deadshot所提到的,用int()包装child.get('id')确实解决了这个问题,但是代码还必须用于同时包含字母和数字的输入,例如id=“node1”、“node15”等

例如:

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

预期:

<root>
    <node id="5" />
    <node id="7" />
    <node id="10" />
</root>
<root>
    <node id="node5" />
    <node id="node7" />
    <node id="node10" />
</root>

您应该将
id
值转换为
int
,并且您可以使用regex从
id

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>

为了进一步构建deadshot的方法,我使用下面的split_key函数,我获取任意时间的字符串(test、test123、123),并将其作为元组拆分为字符串/int部分,以便通过排序方法轻松排序

def split_key(key):
    regex = re.compile(r'^(?P<letters>.*?)(?P<numbers>\d*)$')
    letters = regex.search(key).group('letters') or ''
    numbers = regex.search(key).group('numbers') or 0
    return (letters, int(numbers))

def分割键(键):
regex=re.compile(r'^(?P.*?(-P\d*)$)
字母=正则表达式搜索(键).group('字母')或“”
numbers=regex.search(key.group('numbers')或0
返回(字母、整数(数字))

谢谢!解决了这个谜。。。现在,我如何使这两个int/string都适用,例如,如果id是,我已经用一个适用于format test、test123、123等字符串的答案更新了主要问题。您是否可以使用值
id=“node1”、“node15”
和预期值发布示例output@deadshot-张贴。谢谢你的帮助。看起来我需要查看自然排序,所以我将从这里开始。@user2288151:请将问题和答案分开。如果您有其他或更详细的解决方案,请将其作为新答案发布。@mzjn,分开。谢谢