Python将XML放入字典

Python将XML放入字典,python,xml-parsing,elementtree,Python,Xml Parsing,Elementtree,我有一个如下所示的xml: <root> <G> <G1>1</G1> <G2>some text</G2> <G3>some text</G3> <GP> <GP1>1</GP1> <GP2>a</GP2>

我有一个如下所示的xml:

<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>
我的代码可以很好地获取所有直接位于“G”下的元素,比如G1、G2等,但对于GP,我要么只获取一条记录,要么获取所有记录,但它会重复相同的内容好几次,要么在字典中的一个GP下获取所有9个GP元素。这是我的密码:

    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
code.py:

#/usr/bin/env蟒蛇3
导入系统
将xml.etree.ElementTree作为ET导入
从pprint导入pprint作为pp
FILE_NAME=“data.xml”
def convert_节点(节点,深度_级别=0):
#打印(“*depth\u level+node.tag)
子节点=列表(节点)
如果不是子节点:
return(node.text或“”).strip()
ret_dict=dict()
子节点\u标记=[子节点中项目的item.tag]
子索引=0
对于子节点中的子节点:
tag=child_node.tag
如果子节点标记计数(标记)>1:
sub_obj_dict=ret_dict.get(标记,dict())
子索引+=1
子对象目录[str(子索引)]=转换节点(子节点,深度级别=深度级别+1)
ret_dict[标记]=子对象dict
其他:
ret\u dict[tag]=转换节点(子节点,深度级别=深度级别+1)
返回重新记录
def main():
tree=ET.parse(文件名)
root\u node=tree.getroot()
转换的\u xml=转换的\u节点(根\u节点)
打印(“\n查询指令:\n”)
对于转换的xml中的键:#转换的xml应该是一个只有一个键的字典(在我们的例子中是“G”-我们只关心它的值,以匹配所需的输出)
pp(已转换的xml[键])
如果名称=“\uuuuu main\uuuuuuuu”:
打印(“Python{:s}on{:s}\n.”格式(sys.version,sys.platform))
main()
注释

  • FILE_NAME包含包含输入xml的文件名。请随意更改,以便与您的相匹配
  • 转换在convert_节点中进行。它是一个递归函数,在每个xml节点上调用它并返回一个Python字典(或字符串)。算法:
    • 对于每个节点,获取其(直接)子节点的列表。如果该节点没有任何节点(它是一个叶节点,如G#或GP#节点),它将返回其文本
    • 如果节点有多个子节点具有特定标记,则其内容将添加到表示其索引的键(如G或GP节点)下,并添加到与子标记键对应的当前字典的子字典中
    • 所有具有唯一标记的子项都将其内容放置在与当前词典下的标记相同的键下
    • 没有使用depth_level(您可以删除它),我使用它以树的形式打印xml节点标记;它是xml树中的深度(根-0,G-1,G#,GP-2,GP#-3,…)
  • 该守则旨在:
    • 常规:请注意,没有硬编码的密钥名称
    • 可伸缩性:如果xml在某一点上变得更加复杂(例如,在GP节点下会有一个GPD节点,该节点也会有子节点-基本上xml将获得一个更高的深度级别),那么代码将不加更改地处理它
    • Python3和Python2兼容
输出


我看到了对GPD命名节点的处理,但在示例xml中没有看到这样的节点。这是一个输入错误,很抱歉。应为“GP”。可能是的重复项
    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
(py_064_03.05.04_test0) e:\Work\Dev\StackOverflow\q045799991>"e:\Work\Dev\VEnvs\py_064_03.05.04_test0\Scripts\python.exe" code.py
Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32

Resulting dict(s):

{'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': 'aaa', 'GP3': 'aaa'},
              '2': {'GP1': '2', 'GP2': 'bbb', 'GP3': 'bbb'},
              '3': {'GP1': '3', 'GP2': 'ccc', 'GP3': 'ccc'}}}}