【问题标题】:How does one reorder information in an XML document in python 3?如何在 python 3 中重新排序 XML 文档中的信息?
【发布时间】:2016-08-16 12:12:13
【问题描述】:

假设我有以下 XML 结构

<?xml version="1.0" encoding="utf-8" ?>
<Document>
    <CstmrCdtTrfInitn>
        <GrpHdr>
            <other_tags>a</other_tags> <!--here there might be other nested tags inside <other_tags></other_tags>-->
            <other_tags>b</other_tags> <!--here there might be other nested tags inside <other_tags></other_tags>-->
            <other_tags>c</other_tags> <!--here there might be other nested tags inside <other_tags></other_tags>-->
        </GrpHdr>

        <PmtInf>
            <things>d</things> <!--here there might be other nested tags inside <things></things>-->
            <things>e</things> <!--here there might be other nested tags inside <things></things>-->

            <CdtTrfTxInf>
                <!-- other nested tags here -->
            </CdtTrfTxInf>
        </PmtInf>

        <PmtInf>
            <things>f</things> <!--here there might be other nested tags inside <things></things>-->
            <things>g</things> <!--here there might be other nested tags inside <things></things>-->

            <CdtTrfTxInf>
                <!-- other nested tags here -->
            </CdtTrfTxInf>
        </PmtInf>

        <PmtInf>
            <things>f</things> <!--here there might be other nested tags inside <things></things>-->
            <things>g</things> <!--here there might be other nested tags inside <things></things>-->

            <CdtTrfTxInf>
                <!-- other nested tags here -->
            </CdtTrfTxInf>
        </PmtInf>
    </CstmrCdtTrfInitn>
</Document>    

现在,鉴于这种结构,我想按如下方式操作这些部分:

如果有两个或多个&lt;PmtInf&gt;标签相同:

<things>d</things> <!--here there might be other nested tags inside <things></things>-->
<things>e</things> <!--here there might be other nested tags inside <things></things>-->

我想将整个 &lt;CdtTrfTxInf&gt;&lt;/CdtTrfTxInf&gt; 移动到第一个 &lt;PmtInf&gt;&lt;/PmtInf&gt; 并删除我从 &lt;CdtTrfTxInf&gt;&lt;/CdtTrfTxInf&gt; 中提取的整个 &lt;PmtInf&gt;&lt;/PmtInf&gt;。有点模糊,对吧?这是一个例子:

<Document>
    <CstmrCdtTrfInitn>
        <GrpHdr>
            <other_tags>a</other_tags> <!--here there might be other nested tags inside <other_tags></other_tags>-->
            <other_tags>b</other_tags> <!--here there might be other nested tags inside <other_tags></other_tags>-->
            <other_tags>c</other_tags> <!--here there might be other nested tags inside <other_tags></other_tags>-->
        </GrpHdr>

        <PmtInf>
            <things>d</things> <!--here there might be other nested tags inside <things></things>-->
            <things>e</things> <!--here there might be other nested tags inside <things></things>-->

            <CdtTrfTxInf>
                <!-- other nested tags here -->
            </CdtTrfTxInf>
        </PmtInf>

        <PmtInf>
            <things>f</things> <!--here there might be other nested tags inside <things></things>-->
            <things>g</things> <!--here there might be other nested tags inside <things></things>-->

            <CdtTrfTxInf>
                <!-- other nested tags here -->
            </CdtTrfTxInf>
            <CdtTrfTxInf>
                <!-- other nested tags here -->
            </CdtTrfTxInf>
        </PmtInf>
    </CstmrCdtTrfInitn>
</Document>

如您所见,最后两个 &lt;PmtInf&gt;&lt;/PmtInf&gt; 标记现在变成了一个(因为 &lt;things&gt;&lt;/matched&gt;)并且复制了 &lt;CdtTrfTxInf&gt;&lt;/CdtTrfTxInf&gt;

现在,我想以任何可能的方式执行此操作(lxmlxml.etreexslt 等)。起初,我想使用一些 RegEx 来执行此操作,但它可能会变得有点难看。然后,我想我也许可以使用一些字符串操作,但我不知道该怎么做。

如果 XML 文件的平均大小约为 2k 行,谁能告诉我哪种方法最优雅/最有效?一个例子也将不胜感激。

为了完整起见,我将定义一个函数,它将以字符串形式返回整个 XML 内容:

def get_xml_from(some_file):
    with open(some_file) as xml_file:
        content = xml_file.read()

    return content


def modify_xml(some_file):
    content_of_xml = get_xml_from(some_file)

    # here I should be able to process the XML file

    return processed_xml

我不是在寻找为我做这件事的人,而是在寻求实现这一目标的最佳方法的想法。

【问题讨论】:

  • 不要尝试使用regex 路径,XML 不是常规语言。 “没有 XML 模块”的原因是什么?
  • @DeepSpace XML 是其他文件处理的结果,我没有为此使用 XML 模块。这不是强制性要求,但据我研究 lxmlxml.etree 我没有成功找到一种干净的方法来做到这一点

标签: python xml python-3.x


【解决方案1】:

我不会给你你想要的代码。 相反,我会说你如何去做你想做的事。

首先你要阅读你的xml。所以我将使用xml.etree.ElementTree

import xml.etree.ElementTree as ET
root = ET.fromstring(country_data_as_string)

在此之后,我将忽略树中您不使用的部分,而只是 find CstmrCdtTrfInitn。 由于您只想与PmtInfs 合作,因此您想与其中的findall 合作。

pmt_infs = root.find('.//CstmrCdtTrfInitn').findall('PmtInf')

在此之后,您希望执行算法* 以移动数据上的项目。 如果节点有一个,我将删除第一个子节点。

nodes = []
for node in pmt_infs:
    children = list(node)
    if children:
        node.remove(children[0])
        nodes.append(children[0])

现在我们已经拥有了所有节点,您可以将它们添加到第一个 pmt_infs

pmt_infs[0].extend(nodes)

*您需要将第三个代码块更改为您想要移动节点的方式,因为您将算法从问题的 v1 更改为 v3。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-31
    • 2021-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多