Поиск по шаблону на любой вложенной глубине с использованием xml.etree.ElementTree

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

   <group name="XXX common string">

      <value val="12" description="a dozen">
         <text>one less than a baker's dozen</text>
      </value>

      <value val="13" description="a baker's dozen">
         <text>One more than a dozen</text>
      </value>

   </group>

   <group name="YYY common string">

      <value val="42" description="the answer">
         <text>What do you get if you multiple 6 by 9?</text>
      </value>

   </group>

Есть ли простой способ, используя import xml.etree.ElementTree as ET а также

    parser = ET.XMLParser()
    parser.parser.UseForeignDTD(True)

    if (args.info) or (args.diagnostics):
        print('Parsing input file : ' + inputFileName)

    tree = ET.parse(inputFileName, parser=parser)
    root = tree.getroot()

искать только <group> элементы, имя которых содержит "общую строку" для определенного value val?

Важно: эти группы расположены на разных глубинах в разных файлах.

2 ответа

Это было немного сложно, потому что ваш собственный код не будет работать с примерами данных, которые вы разместили в своем вопросе (например, ничего там не содержит строку errorи нет id атрибуты, и ваш код не для поиска "конкретного valuevalчто казалось одним из твоих требований). Но вот несколько идей...

Для нахождения всех group элементы, которые содержат common string в name атрибут, вы можете сделать что-то вроде этого:

>>> matching_groups = []
>>> for group in tree.xpath('//group[contains(@name, "common string")]'):
...   matching_groups.append[group]
...

Что с учетом ваших данных образца приведет к:

>>> print '\n'.join([etree.tostring(x) for x in matching_groups])
<group name="XXX common string">

      <value val="12" description="a dozen">
         <text>one less than a baker's dozen</text>
      </value>

      <value val="13" description="a baker's dozen">
         <text>One more than a dozen</text>
      </value>

   </group>


<group name="YYY common string">

      <value val="42" description="the answer">
         <text>What do you get if you multiple 6 by 9?</text>
      </value>

   </group>

Если вы хотите ограничить результаты только group элементы, которые содержат value элемент с атрибутом val == 42Вы можете попробовать:

>>> matching_groups = []
>>> for group in tree.xpath('//group[contains(@name, "common string")][value/@val = "42"]'):
...     matching_groups.append(group)
... 

Что даст:

>>> print '\n'.join([etree.tostring(x) for x in matching_groups])
<group name="YYY common string">

      <value val="42" description="the answer">
         <text>What do you get if you multiple 6 by 9?</text>
      </value>

   </group>

Проблемы заключались в 1) поиске по групповому имени группы и 2) том факте, что группы были размещены на разных уровнях в разных файлах.

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

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

    import xml.etree.ElementTree as ET

    parser = ET.XMLParser()
    parser.parser.UseForeignDTD(True)

    tree = ET.parse(inputFileName, parser=parser)
    root = tree.getroot()

    args.errorDefinitions = {}
    for element in tree.iter():
        if element.tag == 'group':
            if 'error' in element.get('name').lower():
                if element._children:
                    for errorMessage in element._children[0]._children:
                        args.errorDefinitions[errorMessage.get('name')] = \
                                  {'id':  errorMessage.get('id'), \
                                  'description': element._children[0].text}
Другие вопросы по тегам