首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Python将XML兄弟姐妹放入字典中

Python将XML兄弟姐妹放入字典中
EN

Stack Overflow用户
提问于 2017-08-21 14:43:41
回答 1查看 810关注 0票数 1

我有一个如下所示的xml:

代码语言:javascript
运行
复制
<root>
    <G>
        <G1>1</G1>
        <G2>some text</G2>
        <G3>some text</G3>
        <GP>
            <GP1>1</GP1>
            <GP2>a</GP2>
            <GP3>a</GP3>
        </GP>
        <GP>
            <GP1>2</GP1>
            <GP2>b</GP2>
            <GP3>b</GP3>
        </GP>
        <GP>
            <GP1>3</GP1>
            <GP2>c</GP2>
            <GP3>c</GP3>
        </GP>
    </G>
    <G>
        <G1>2</G1>
        <G2>some text</G2>
        <G3>some text</G3>
        <GP>
            <GP1>1</GP1>
            <GP2>aa</GP2>
            <GP3>aa</GP3>
        </GP>
        <GP>
            <GP1>2</GP1>
            <GP2>bb</GP2>
            <GP3>bb</GP3>
        </GP>
        <GP>
            <GP1>3</GP1>
            <GP2>cc</GP2>
            <GP3>cc</GP3>
        </GP>
    </G>
    <G>
        <G1>3</G1>
        <G2>some text</G2>
        <G3>some text</G3>
        <GP>
            <GP1>1</GP1>
            <GP2>aaa</GP2>
            <GP3>aaa</GP3>
        </GP>
        <GP>
            <GP1>2</GP1>
            <GP2>bbb</GP2>
            <GP3>bbb</GP3>
        </GP>
        <GP>
            <GP1>3</GP1>
            <GP2>ccc</GP2>
            <GP3>ccc</GP3>
        </GP>
    </G>
</root>

我试图将这个xml转换成一个名为“G”的嵌套字典:

代码语言:javascript
运行
复制
{ 1: {G1: 1,
      G2: some text,
      G3: some text,
      GP: { 1: {GP1: 1,
                GP2: a,
                GP3: a},
            2: {GP1: 2,
                GP2: b,
                GP3: b},
            3: {GP1: 3,
                GP2: c,
                GP3: c}}
      },
  2: {G1: 2,
      G2: some text,
      G3: some text,
      GP: { 1: {GP1: 1,
                GP2: aa,
                GP3: aa},
            2: {GP1: 2,
                GP2: bb,
                GP3: bb},
            3: {GP1: 3,
                GP2: cc,
                GP3: cc}}
      },
  3: {G1: 3,
      G2: some text,
      G3: some text,
               GP: { 1: {GP1: 1,
                GP2: a,
                GP3: a},
            2: {GP1: 2,
                GP2: bbb,
                GP3: bbb},
            3: {GP1: 3,
                GP2: ccc,
                GP3: ccc}}
      }
    }

我的代码可以很好地得到所有在"G“下面的元素,所以G1、G2等等,但是对于GP,我要么只得到一条记录,要么得到所有的记录,但是它重复了相同的东西--几次--我在字典中的一个GP下得到了所有的9个GP元素。这是我的代码:

代码语言:javascript
运行
复制
    f = 'path to file'
    tree = ET.parse(f)
    root = tree.getroot()
    self.tree = tree
    self.root = root
    gs = len(self.tree.getiterator('G'))
    g = {}
    for i in range(0, gs):
        d = {}
        for elem in self.tree.getiterator('G')[i]:
            if elem.text == "\n      " and elem.tag not in ['GP']:
                    dd = {}
                    for parent in elem:
                        if parent.text == "\n        ":
                            ddd = {}
                            for child in parent:
                                ddd[child.tag] = child.text
                            dd[parent.tag] = ddd
                        else:
                            dd[parent.tag] = parent.text
                    d[elem.tag] = dd
            else:
                d[elem.tag] = elem.text
        g[i+1] = d

    # Build GP
    count = 0
    gp = {}
    for elem in self.tree.getiterator('GP'):
        d = {}
        for parent in elem:
            if parent.text == "\n      ":
                dd = {}
                for child in parent:
                    dd[child.tag] = child.text
                d[parent.tag] = dd
            else:
                d[parent.tag] = parent.text
        count += 1
        gp[count] = d
    g["GP"] = gp
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-21 19:16:08

code.py

代码语言:javascript
运行
复制
#!/usr/bin/env python3

import sys
import xml.etree.ElementTree as ET
from pprint import pprint as pp


FILE_NAME = "data.xml"


def convert_node(node, depth_level=0):
    #print("  " * depth_level + node.tag)
    child_nodes = list(node)
    if not child_nodes:
        return (node.text or "").strip()
    ret_dict = dict()
    child_node_tags = [item.tag for item in child_nodes]
    child_index = 0
    for child_node in child_nodes:
        tag = child_node.tag
        if child_node_tags.count(tag) > 1:
            sub_obj_dict = ret_dict.get(tag, dict())
            child_index += 1
            sub_obj_dict[str(child_index)] = convert_node(child_node, depth_level=depth_level + 1)
            ret_dict[tag] = sub_obj_dict
        else:
            ret_dict[tag] = convert_node(child_node, depth_level=depth_level + 1)
    return ret_dict


def main():
    tree = ET.parse(FILE_NAME)
    root_node = tree.getroot()
    converted_xml = convert_node(root_node)
    print("\nResulting dict(s):\n")
    for key in converted_xml: # converted_xml should be a dictionary having only one key (in our case "G" - we only care about its value, to match the required output)
        pp(converted_xml[key])


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

Notes

  • FILE_NAME包含包含输入xml的文件名。请随意改变它,以便与你的相匹配。
  • 转换发生在convert_node中。它是一个递归函数,它在每个xml节点上调用,并返回一个Python字典(或字符串)。算法:
    • 对于每个节点,获取其(直接)子节点的列表。如果节点没有(它是一个叶节点--比如G#或GP#节点),它将返回它的文本
    • 如果该节点有多个具有特定标记的子节点,则其内容将在表示其索引的键(如G或GP节点)下添加到与子标记键对应的当前字典的子字典中。
    • 所有具有唯一标签的子类都会将其内容放在与当前字典中的标签相等的键下。
    • 不使用depth_level (您可以删除它),我使用它以树形式打印xml节点标记;它是xml树的深度(根- 0,G-1,G#,GP - 2,GP# - 3,.)

  • 代码设计为:
    • 一般情况:注意有,没有硬编码的密钥名
    • 可扩展性:如果在某个时候xml将变得复杂(例如,在GP节点下将有一个GP__D节点,例如,该节点也将有子节点--基本上,xml将获得一个更深的级别),代码将处理它,而无需更改。
    • Python 3和Python 2兼容

输出

( e:\Work\Dev\StackOverflow\q045799991>"e:\Work\Dev\VEnvs\py_064_03.05.04_test0\Scripts\python.exe“code.py Python3.5.4) (v3.5.4:3f56838,2017年8月8日,02:17:05) MSC v.1900 64位(AMD64),其结果是:{'1':{'G1':'1','G2':‘一些文本’,'G3':‘一些文本’,'GP':{'1':{'GP1':'1','GP2':'a','GP3':'a'},'2':{'GP1':'2','GP2':'b','GP3':'b'},'3':{'GP1':'3','GP2':'c','GP3':‘C’}},'2':{'G1':'2','G2':‘一些文本’,'G3':‘一些文本’,'GP':{'1':{'GP1':'1','GP2':'aa','GP3':'aa'},'2':{'GP1':'2','GP2':'bb','GP3':'bb'},'3':{'GP1':'3','GP2':'cc','GP3':‘cc’}},'3':{'G1':'3','G2':‘一些文本’,'G3':'some text','GP':{'1':{'GP1':'1','GP2':'aaa','GP3':'aaa'},'2':{'GP1':'2','GP2':'bbb','GP3':'bbb'},'3':{'GP1':'3',‘GP3 2’:'ccc','GP3':‘ccc’}

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45799991

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档