LXML-排序标记Ord

2024-09-27 20:18:31 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个遗留文件格式,我正在将其转换为XML进行处理。该结构可概括为:

<A>
    <A01>X</A01>
    <A02>Y</A02>
    <A03>Z</A03>
</A>

标记的数字部分可以从01到99,并且可能有间隙。作为处理的一部分,某些记录可能添加了其他标记。处理完成后,我通过遍历树将文件转换回传统格式。文件相当大(大约150000个节点)。

这方面的一个问题是,某些使用传统格式的软件假设标记(或者更确切地说,在转换时字段)将按字母数字顺序排列,但默认情况下,新标记将添加到分支的末尾,这将导致它们以错误的顺序从迭代器中出来。

每次我来添加一个新的标记时,我都可以使用xpath根据标记名来查找前面的兄弟,但我的问题是,是否有一种更简单的方法在导出之前立即对树进行排序?

编辑:

我想我把结构总结得太多了。

一个记录可以包含如上所述的多个级别,以提供如下内容:

<X>
    <X01>1</X01>
    <X02>2</X02>
    <X03>3</X03>
    <A>
        <A01>X</A01>
        <A02>Y</A02>
        <A03>Z</A03>
    </A>
    <B>
        <B01>Z</B02>
        <B02>X</B02>
        <B03>C</B03>
    </B>
</X>

Tags: 文件标记格式记录数字传统结构x03
2条回答

您可以对xml元素进行如下排序:

from operator import attrgetter
from lxml import etree

root = etree.parse(xmlfile)
children = list(root)
sorted_list = sorted(children, key=attrgetter('tag'))

如果运行速度太慢,您可以对标记名进行排序,然后使用xpath获取节点:

tag_list = [item.tag for item in root]
sorted_taglist = sorted(tag_list)

可以编写一个helper函数来在正确的位置插入一个新元素,但是如果不了解更多关于结构的信息,就很难使它成为泛型。

下面是对整个文档中的子元素进行排序的简短示例:

from lxml import etree

data = """<X>
    <X03>3</X03>
    <X02>2</X02>
    <A>
        <A02>Y</A02>
        <A01>X</A01>
        <A03>Z</A03>
    </A>
    <X01>1</X01>
    <B>
        <B01>Z</B01>
        <B02>X</B02>
        <B03>C</B03>
    </B>
</X>"""

doc = etree.XML(data,etree.XMLParser(remove_blank_text=True))

for parent in doc.xpath('//*[./*]'): # Search for parent elements
  parent[:] = sorted(parent,key=lambda x: x.tag)

print etree.tostring(doc,pretty_print=True)

屈服:

<X>
  <A>
    <A01>X</A01>
    <A02>Y</A02>
    <A03>Z</A03>
  </A>
  <B>
    <B01>Z</B01>
    <B02>X</B02>
    <B03>C</B03>
  </B>
  <X01>1</X01>
  <X02>2</X02>
  <X03>3</X03>
</X>

相关问题 更多 >

    热门问题