Как пройти через XML дочерние элементы дерева от выбранного родителя? - PullRequest
0 голосов
/ 26 февраля 2020

Я хочу пройтись по моему дереву XML и извлечь все дочерние атрибуты из выбранного родителя. Это моя настройка синтаксического анализа:

import xml.etree.ElementTree as ET

file_name = 'myXML.xml'
tree = ET.parse(file_name)
root = tree.getroot()

Функция, которую я использую для l oop, но вам понадобится для l oop на слой поколений: по сути, каждый родительский цикл проходит через каждого потомка и возвращает .tag, .text, & .attrib:

Есть ли способ циклического прохождения и сбора всех этих данных без знания количества слоев?

def data_dump(k, mD, st):
    for na in mD.iter(k):
        for a in na:
            print(st + '> a:: ', a.tag., a.text, a.attrib)
            for b in a:
                print('|-->', ' b:: ', b.tag, b.text, b.attrib)
                for c in b:
                    print('|---->', ' c:: ', c.tag, c.text, c.attrib)
                    for d in c:
                        print('|------>', ' d:: ', d.tag, d.text, d.attrib)

Эти мои тестовые случаи:

data_dump('Title', root, 'TITLE')
data_dump('Comment', root, 'COM')
data_dump('Steps', root, 'STEP')
data_dump('Transitions', root, 'TRANS')
data_dump('Branches', root, 'BRAN')
data_dump('Connections', root, 'CONN')
data_dump('Sequence', root, 'SEQ')

1 Ответ

1 голос
/ 26 февраля 2020

Ваша реализация очень неэффективна. Использование пяти циклов может значительно увеличить время выполнения при увеличении элементов в XML. Другими словами, O (n ^ 5) просто ужасно.

Что бы я порекомендовал для вашей проблемы - это использовать XPath, подробнее здесь .

import xml.etree.ElementTree as ET
root = ET.parse(filename)
result = ''

for elem in root.findall('.//child/grandchild'):
    if elem.attrib.get('name') == 'foo':
        result = elem.text
        break

Вы можете включить ту же идею в свою функцию и превратить ее в нечто вроде

def data_dump(element,value):
    for elem in root.findall('.//parent/'+element):
        if elem.attrib.get('name') == value:
            text,attrib,tag = elem.text,elem.attrib,elem.tag
            break

...