Python ElementTree.Element отсутствует текст? - PullRequest
0 голосов
/ 05 мая 2018

Итак, я разбираю этот xml-файл среднего размера (около 27K строк). Не так далеко, я вижу неожиданное поведение от ElementTree.Element, где я получаю Element.text для одной записи, но не для следующей, но она есть в исходном XML, как вы можете видеть:

<!-- language: lang-xml -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:enumeration value="24">
   <xs:annotation>
      <xs:documentation>UPC12 (item-specific) on cover 2</xs:documentation>
      <xs:documentation>AKA item/price; ‘cover 2’ is defined as the inside front cover of a book</xs:documentation>
   </xs:annotation>
</xs:enumeration>
<xs:enumeration value="25">
   <xs:annotation>
      <xs:documentation>UPC12+5 (item-specific) on cover 2</xs:documentation>
      <xs:documentation>AKA item/price; ‘cover 2’ is defined as the inside front cover of a book</xs:documentation>
   </xs:annotation>
</xs:enumeration>

Когда я сталкиваюсь с тегом перечисление , я вызываю эту функцию:

import xml.etree.cElementTree as ElementTree
...
    def _parse_list_item(xmlns: str, list_id: int, itemElement: ElementTree.Element) -> ListItem:
      if isinstance(itemElement, ElementTree.Element):
        if itemElement.attrib['value'] is not None:
            item_id = itemElement.attrib['value']  # string
            if list_id == 6 and (item_id == '25' or item_id=='24'):
                print(list_id, item_id)  # <== debug break point here
            desc = None
            notes = ""
            for child in itemElement:
                if child.tag == (xmlns + 'annotation'):
                    for grandchild in child:
                        if grandchild.tag == (xmlns + 'documentation'):
                            if desc is None:
                                desc = grandchild.text
                            else:
                                if len(notes)>0:
                                    notes += " "  # add a space
                                notes += grandchild.text or ""
            if item_id is not None and desc is not None:
                return Codex.ListItem({'itemId': item_id, 'listId': list_id, 'description': desc, 'notes': notes})

Если я поставлю точку останова в операторе печати, когда я доберусь до узла перечисления для «24», я смогу посмотреть на текст для узлов внука, и они такие, как показано в XML, то есть «UPC12 ...» или "элемент АКА ...", но когда я добираюсь до узла перечисления для "25" и смотрю на текст внука, это - Нет.

Когда я удаляю пространство имен xs: путем предварительной фильтрации XML-файла, текст внука проходит нормально.

Возможно, у меня превышен какой-то размер или есть какая-то проблема с синтаксисом?
Извините за менее чем pythonic код, но я хотел иметь возможность проверить все промежуточные значения в pycharm. Это питон 3.6.

Спасибо за любые идеи, которые вы можете иметь!

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Итак, в конечном итоге я решил свою проблему, запустив предварительный процесс для файла XML, чтобы удалить пространство имен xs: из всех тегов открытия / закрытия XML, и затем я смог успешно обработать файл, используя функцию как определено выше. Не уверен, почему пространства имен вызывают проблемы, но, возможно, в cElementTree есть ошибка для префиксов пространства имен в больших файлах XML. Для @mzjn - я ожидаю, что будет трудно создать минимальный пример, так как он правильно обрабатывает сотни элементов, прежде чем он завершится сбоем, поэтому мне, по крайней мере, придется предоставить довольно большой файл XML. Тем не менее, спасибо за то, что вы звучите как доска.

0 голосов
/ 06 мая 2018

В цикле for это условие никогда не выполняется: if child.tag == (xmlns + 'annotation'):.

Почему?

Попробуйте вывести метку ребенка. Если мы предположим, что ваше пространство имен (xmlns) равно 'Steve', тогда:

print(child.tag) выведет: {Steve}annotation, а не Steveannotation.

Итак, учитывая этот факт, if child.tag == (xmlns + 'annotation'): всегда False.
Вы должны изменить его на: if child.tag == ('{'+xmlns+'}annotation'):

Используя ту же логику, вы обнаружите, что вам также придется изменить это условие:

if grandchild.tag == (xmlns + 'documentation'):

до:

if grandchild.tag == ('{'+xmlns+'}documentation'):
...