Невозможно вернуть дочерние значения при разборе xml с использованием etree - PullRequest
0 голосов
/ 20 марта 2020

У меня есть xml файл, который выглядит как

<?xml version="1.0" encoding="UTF-8" ?>
<FullReport
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <firm>1426</firm>
    <reportDate>07FEB2020_18:00:00.000000</reportDate>
    <rooms>
        <room>
            <roomID>PCHAT-0x0000000000000637</roomID>
            <roomTitle>FX - WBB - CTON</roomTitle>
            <description>global chat</description>
            <creationDate></creationDate>
            <removalDate></removalDate>
            <lastActivityDate>02/07/2020 12:26:24</lastActivityDate>
            <status>Active</status>
            <membership>Bilateral</membership>
            <isAnonymous>false</isAnonymous>
            <hasActiveAdmins>true</hasActiveAdmins>
            <activeUserCount>17</activeUserCount>
            <distinctFirmsInRoom>2</distinctFirmsInRoom>
            <isInternalOnly>false</isInternalOnly>
            <isIncognitoForum>false</isIncognitoForum>
        </room>
        <users>
            <uuid>6820</uuid>
            <bbgEmail>SJONES@Bloomberg.net</bbgEmail>
            <fullName>SEAN JONES</fullName>
            <firmName>BANK OF TEST</firmName>
            <firmNumber>1400</firmNumber>
            <accountNumber>51067</accountNumber>
            <accountName>BANK OF TEST</accountName>
            <inviteDate>01/07/2013 22:00:39</inviteDate>
            <isDeleted>false</isDeleted>
            <isAdmin>false</isAdmin>
            <isCreator>false</isCreator>
            <roomAlias>CTON</roomAlias>
            <corpEmail>sean.jones@botest.com</corpEmail>
            <city>LONDON</city>
        </users>
        <users>
            <uuid>6820</uuid>
            <bbgEmail>SSMITH@Bloomberg.net</bbgEmail>
            <fullName>SEAN SMITH</fullName>
            <firmName>BANK OF TEST</firmName>
            <firmNumber>1400</firmNumber>
            <accountNumber>51067</accountNumber>
            <accountName>BANK OF TEST</accountName>
            <inviteDate>01/07/2013 22:00:39</inviteDate>
            <isDeleted>false</isDeleted>
            <isAdmin>false</isAdmin>
            <isCreator>false</isCreator>
            <roomAlias>CTON</roomAlias>
            <corpEmail>sean.smith@botest.com</corpEmail>
            <city>LONDON</city>
        </users>
</FullReport>
</FullReport>

Я анализирую данные, используя следующий код:

import xml.etree.cElementTree as et

tree = et.parse('test.xml')
print (tree.getroot())
root = tree.getroot()
print ("tag=%s, attrib=%s" % (root.tag, root.attrib))

for child in root:
        print (child.tag, child.attrib)
        if child.tag == "room":
            for step_child in child:
                print (step_child.tag)

# get the information via the children!
print ("-" * 40)
print ("Iterating using a getchildren()")
print ("-" * 40)
rooms = root.getchildren()
for room in rooms:
    room_children = room.getchildren()
    for room_child in room_children:
        print ("%s=%s" % (room_child.tag, room_child.text))

Когда я печатаю room_child.tag и room_child .txt Я не вижу значения? Совершенно новичок в этом, так что я не уверен, что мне не хватает?

Получены следующие результаты:

enter image description here

Моя конечная цель - перебирать каждое значение и конвертировать в CSV, но я застрял при доступе к значениям и не уверен, почему данные не возвращаются. Я хотел бы, чтобы конечный CSV выглядел примерно так, как в строке для каждого пользователя в CSV

enter image description here

1 Ответ

1 голос
/ 22 марта 2020

Когда вы запускаете for child in root:, тогда эта l oop повторяет только по прямым потомкам FullReport , в вашем случае: фирма , reportDate и комнаты , поэтому у нее нет шансов попасть в комнату , которая расположена на шаг ниже.

Из вашего кода (первый l oop) Я вижу, что на самом деле вас интересуют прямые потомки FullReport / rooms / room .

Чтобы напечатать их имена тегов и текстовое содержимое, вы можете запустить, например:

for child in root.iter('room'):
    for step_child in child:
        print(f'{step_child.tag:20} {step_child.text}')

Для вашего примера ввода результат будет следующим:

roomID               PCHAT-0x0000000000000637
roomTitle            FX - WBB - CTON
description          global chat
creationDate         None
removalDate          None
lastActivityDate     02/07/2020 12:26:24
status               Active
membership           Bilateral
isAnonymous          false
hasActiveAdmins      true
activeUserCount      17
distinctFirmsInRoom  2
isInternalOnly       false
isIncognitoForum     false

А что касается вашего последнего задания, вы можете выполнить:

rows = []
for child in root.iter('rooms'):
    roomId, roomTitle = 'id', 'ttl'
    for it in child:
        if it.tag == 'room':
            roomId = it.findtext('roomID')
            roomTitle = it.findtext('roomTitle')
        elif it.tag == 'users':
            rows.append([roomId, roomTitle, it.findtext('uuid'), it.findtext('bbgEmail'),
                it.findtext('fullName'), it.findtext('firmName')])
df = pd.DataFrame(rows, columns=['roomId', 'roomTitle', 'uuid', 'bbgEmail',
    'fullName', 'firmName'])

Код выше исходя из предположения, что элемент room появляется первым, а после них идут элементы users .

И добавьте код, касающийся любых дополнительных столбцов, не показанных в вашем сообщении.

...