使用python解析嵌套的XML

时间:2018-06-28 14:19:01

标签: python xml xml-parsing

我正在尝试使用python解析嵌套XML。示例文件格式如下:

<repositoryFileTreeDto>
    <children>
        <children>
            <file>
                <name> File1 </name>
                <path> home/user1/File1.txt </path>
            </file>
        </children>
        <children>
            <file>
                <name> File2 </name>
                <path> home/user1/File2.txt </path>
            </file>
        </children>
        <file>
            <name> User1 </name>
            <path> home/user1 </path>
        </file>
    </children>
    <children>
        <file>
            <name> User2 </name>
            <path> home/user2 </path>
        </file>
    </children>
    <children>
        <file>
            <name> User3 </name>
            <path> home/user3 </path>
        </file>
    </children>
    <children>
        <children>
            <file>
                <name> File4 </name>
                <path> home/user4/File4.txt </path>
            </file>
        </children>
        <file>
            <name> User4 </name>
            <path> home/user4 </path>
        </file>
    </children>
    <file>
        <name> Home </name>
        <path> /home </path>
    </file>
</repositoryFileTreeDto>

我要打印“空使用”文件夹和“非空用户”文件夹(即具有1个或多个文件的用户)。

此处是XML代码段。

用户2和用户3是空文件夹,用户1是非空用户。

识别空用户和非空用户的条件:

如果用户在同一级别具有任何标签,则为非空用户。如果用户没有标签,则为空用户。

示例代码1:

import xml.etree.ElementTree as ET
import time
import requests
import csv
tree = ET.parse('tree.xml')
root = tree.getroot()
for child in root.findall('children'):
    for subchlid in child.findall('file'):
        title = subchlid.find('title').text
        print(title)
    for subchlid1 in child.findall('children'):
        if subchlid1.tag == 'children':
            print(subchlid1.tag)

代码输出1:

User1
File1
File2
User2
User3
User4
File4

示例代码2:

import xml.etree.ElementTree as ET
import time
import requests
import csv
tree = ET.parse('tree.xml')
root = tree.getroot()
list_values = []
dicts = {}
for child in root.findall('children'):
    for sub_child in child.findall('file'):
        username = sub_child.find('title').text

    for sub_child1 in child.findall('children'):
        for sub_child2 in sub_child1.findall('file'):
            file_path = sub_child2.find('path').text
            file_title = sub_child2.find('title').text
        #print(username)
        #print(file_title)
        list_values.append(file_title)
        for user in username:
            dicts[username] = list_values
print(dicts)

代码输出2:

{'User1': ['File1', 'File2'],'User4': ['File1', 'File2', 'File4']}

此输出中的User2和User3不属于Dict,因为它是一个空文件夹,并且User4正在共享User1文件。

预期输出:

The number of Empty Users: 2
The number of Non-Empty Users: 2
User1 Files are: File1, File2
User4 files are: File4

谢谢大家。

1 个答案:

答案 0 :(得分:0)

如果您愿意使用lxml软件包,则可以使用xpath获得结果。

from lxml import etree
from operator import itemgetter
from collections import defaultdict

first = itemgetter(0)
with open('tree.xml') as fp:
    xml = etree.fromstring(fp.read())

# create a user dictionary and a file dictionary
udict = {first(e.xpath('path/text()')).strip(): first(e.xpath('name/text()')).strip()
         for e in xml.xpath('children/file')}

fdict = {first(e.xpath('path/text()')).strip(): first(e.xpath('name/text()')).strip()
         for e in xml.xpath('children/children/file')}

ufdict = defaultdict(list)

for k,v in fdict.items():
    ufdict[first(k.rsplit('/',1))].append(v)

out = {v: ufdict.get(k, []) for k, v in udict.items()}

print('The number of Empty Users: {}'.format(len([v for v in out.values() if not v]))
print('The number of Non-Empty Users: {}'.format(len([v for v in out.values() if not v]))
for k, v in out.items():
    if v:
        print(f'{k} files are {", ".join(v)}')