Как в Python проверить определенный раздел XML и извлечь текст узла?

Я использую minidom для проверки XML, который содержит список списков ключей отладки. Пример XML выглядит следующим образом:

<Shortcuts>
  <Item>
    <CommandName>DebugCommandName_1</CommandName>
    <ShortcutKeys>
      <Item>
        <Keys>
          <Item>KEY_1</Item>
          <Item>KEY_2</Item>
        </Keys>
      </Item>
    </ShortcutKeys>
  </Item>
...
  <Item>
    <CommandName>DebugCommandName_2</CommandName>
    <ShortcutKeys>
      <Item>
        <Keys>
          <Item>KEY_3</Item>
        </Keys>
      </Item>
      <Item>
        <Keys>
          <Item>KEY_4</Item>
        </Keys>
      </Item>
    </ShortcutKeys>
  </Item>
</Shortcuts>

По причинам, не зависящим от меня, я не могу требовать, чтобы формат входящего XML был изменен, чтобы быть более последовательным, поэтому я должен учитывать оба макета разделов документа ShortcutKeys, а также несколько дочерних элементов Item. над местом.

Анализируя XML с помощью minidom, я затем использую следующий Python для извлечения содержимого:

for item in parsedKeyComboFile.getElementsByTagName("Item"):
if (item.getElementsByTagName("CommandName").length > 0): 
    commandName = item.getElementsByTagName("CommandName")[0].childNodes[0].nodeValue
    print(commandName)
elif (item.getElementsByTagName("Keys").length > 0):
    keyCombo = item.getElementsByTagName("Item")[0].childNodes[0].nodeValue
    print(keyCombo)

Со временем я добавлю эту информацию в словари, но на данный момент я получаю распечатку приведенного выше XML:

DebugCommandName_1
KEY_1
DebugCommandName_2
KEY_3
KEY_4

когда я желаю:

DebugCommandName_1
KEY_1 KEY_2
DebugCommandName_2
KEY_3 KEY_4

(Я понимаю, что неправильно форматирую вывод ключей для получения однострочного вывода. Главное здесь — не пропустить элемент KEY_2.)

Я знаю, что [0] в строке keyCombo= ограничивает меня первым вхождением Item в Keys.

Итак, есть ли у меня способ проверить элемент верхнего уровня и все его дочерние элементы, вытащив единственное имя команды и все элементы ключей внутри этого элемента верхнего уровня, прежде чем перейти к следующему элементу верхнего уровня и повторить процесс? Я совершенно не смог добиться этого до сих пор.

Должен ли я использовать ElementTree?

Большое спасибо.


person Graham Campbell    schedule 01.08.2017    source источник


Ответы (2)


У меня нет опыта работы с minidom, и по рекомендации

Его использование не рекомендуется, вы, вероятно, захотите использовать вместо него xml.etree.ElementTree.

-- из информации тега minidom

Если вместо этого вы можете использовать xml.etree.ElementTree, это может быть простым способом:

import xml.etree.ElementTree as ET
tree = ET.parse('example.xml')
root = tree.getroot()  # unused variable in this example

for elem in tree.iter():
    if elem.tag == 'CommandName':
        print(elem.text)
    if elem.tag == 'Keys': 
        for item in elem:
            print(item.text)

Отпечатки

DebugCommandName_1
KEY_1
KEY_2
DebugCommandName_2
KEY_3
KEY_4

Или, если вам нужны списки для каждого тега <Keys>:

if elem.tag == 'Keys':
    print([item.text for item in elem])

Отпечатки:

DebugCommandName_1
['KEY_1', 'KEY_2']
DebugCommandName_2
['KEY_3']
['KEY_4']
person davedwards    schedule 01.08.2017
comment
Отлично, и спасибо, что указали на то, что я явно пропустил в документации minidom! - person Graham Campbell; 02.08.2017

Я не могу комментировать, так как я ниже порога, поэтому, пожалуйста, простите меня за то, что я поставил это в качестве ответа.

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

XML-запрос Python Minidom

person ttallierchio    schedule 01.08.2017