Python 3 анализирует xml-файл с помощью ElementTree

Помогите, у меня есть следующий файл XML, из которого я пытаюсь прочитать и извлечь данные, ниже приведена выдержка из файла xml,

<Variable name="Inboard_ED_mm" state="Output" type="double[]">17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154<Properties><Property name="index">25</Property><Property name="description"></Property><Property name="upperBound">0</Property><Property name="hasUpperBound">false</Property><Property name="lowerBound">0</Property><Property name="hasLowerBound">false</Property><Property name="units"></Property><Property name="enumeratedValues"></Property><Property name="enumeratedAliases"></Property><Property name="validity">true</Property><Property name="autoSize">true</Property><Property name="userSlices"></Property></Properties></Variable>

Я пытаюсь извлечь следующее: 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154

Я рассмотрел пример здесь, xml.etree.ElementTree — ElementTree XML API, и я могу заставить этот пример работать, но когда я изменяю код для приведенного выше XML, код ничего не возвращает!

Вот мой код,

import xml.etree.ElementTree as ET
work_dir = r"C:\Temp\APROCONE\Python"

with open(model.xml, 'rt') as f:
    tree = ET.parse(f)
    root = tree.getroot()

for Variable in root.findall('Variable'):
    type = Variable.find('type').text
    name = Variable.get('name')
    print(name, type)

Любые идеи? Заранее благодарю за любую помощь.

Редактировать: Спасибо всем, кто прокомментировал. С вашим советом я поиграл и поискал и получил следующий код,

with open(os.path.join(work_dir, "output.txt"), "w") as f:
for child1Tag in root.getchildren():
    for child2Tag in child1Tag.getchildren():
        for child3Tag in child2Tag.getchildren():
            for child4Tag in child3Tag.getchildren():
                for child5Tag in child4Tag.getchildren():
                    name = child5Tag.get('name')
                    if name == "Inboard_ED_mm":
                        print(child5Tag.attrib, file=f)
                        print(name, file=f)
                        print(child5Tag.text, file=f)

Чтобы вернуть следующее,

{'name': 'Inboard_ED_mm', 'state': 'Output', 'type': 'double[]'}
Inboard_ED_mm
17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154, 17.154

Я знаю, что это не лучший код в мире, любые идеи о том, как упростить код, будут очень приветствоваться.


person James    schedule 18.10.2018    source источник
comment
ниже приведена выдержка из XML-файла. Проблема может заключаться в том, что Variable находится в пространстве имен по умолчанию. У вас есть xmlns="???" где-нибудь в XML, который не показан?   -  person Daniel Haley    schedule 18.10.2018
comment
@ Дэниел Хейли, спасибо за ответ, извините, нет, я не могу найти «xmlns» в файле.   -  person James    schedule 19.10.2018


Ответы (2)


Вы говорите, что приведенное выше является «извлечением» из XML-файла. Структура XML важна. Вышесказанное просто находится внутри корневого узла?

for Variable in root.findall('Variable'):
    print(Variable.get('name'), Variable.text)

Или он существует где-то глубже в структуре дерева XML, на известном уровне?

for Variable in root.findall('Path/To/Variable'):
    print(Variable.get('name'), Variable.text)

Или он существует на каком-то неуказанном более глубоком уровне в древовидной структуре XML?

for Variable in root.findall('.//Variable'):
    print(Variable.get('name'), Variable.text)

Демонстрация последних двух:

>>> import xml.etree.ElementTree as ET
>>> src = """
<root>
 <SubNode>
  <Variable name='x'>17.154, ..., 17.154<Properties>...</Properties></Variable>
  <Variable name='y'>14.174, ..., 15.471<Properties>...</Properties></Variable>
 </SubNode>
</root>"""
>>> root = ET.fromstring(src)
>>> for Variable in root.findall('SubNode/Variable'):
        print(Variable.get('name'), Variable.text)


x 17.154, ..., 17.154
y 14.174, ..., 15.471
>>>
>>> for Variable in root.findall('.//Variable'):
        print(Variable.get('name'), Variable.text)


x 17.154, ..., 17.154
y 14.174, ..., 15.471

Обновить

Основываясь на вашем новом/более четком/обновленном вопросе, вы ищете:

for child in root.findall("*/*/*/*/Variable[@name='Inboard_ED_mm']"):
    print(child.attrib, file=f)
    print(child.get('name'), file=f)
    print(child.text, file=f)

or

for child in root.findall(".//Variable[@name='Inboard_ED_mm']"):
    print(child.attrib, file=f)
    print(child.get('name'), file=f)
    print(child.text, file=f)

С точными именами тегов с 1 по 4 мы могли бы дать вам более точный XPath, вместо того, чтобы полагаться на */*/*/*/.

person AJNeufeld    schedule 18.10.2018
comment
спасибо за ваш ответ, после того, как вы немного поиграли и поискали, он находится глубоко в корневом узле! Я добавил код в исходный вопрос. - person James; 19.10.2018
comment
Ах, вы ищете тег Variable с точным атрибутом name. Для этого есть XPath. Смотрите обновление. - person AJNeufeld; 19.10.2018

Ваш корневой узел уже является тегом Variable, поэтому вы не найдете ничего с тегом Variable с findall, который может искать только дочерние узлы. Вместо этого вы должны просто вывести атрибут text корневого узла:

print(root.text)
person blhsing    schedule 18.10.2018
comment
спасибо за ответ, ваш ответ помог мне найти решение. - person James; 19.10.2018