XML-анализ игнорирует текст - PullRequest
0 голосов
/ 15 января 2019

У меня следующая проблема: я пытаюсь получить информацию из набора файлов xml в python. Я не делаю ничего особенного, например:

import xml.etree.ElementTree as ET

root = ET.parse(r'C:\Documents\XMLfolder\file.xml').getroot()
info = root.find('foo').find('bar').find('info').text

Это работает с большей частью имеющейся у меня информации, но один раздел xml имеет следующий формат:

<bar>
<info id="1"><label>1</label>SampleTextHere</info>
</bar>

Приведенный выше код дает None - хотя я могу найти элемент info и элемент label. Я просто не могу найти текст. Если я отредактирую файл для удаления <label> 1 </label>, то приведенный выше код вернет нужный мне текст.

Есть ли что-то очень простое, что я не знаю, что позволило бы мне получить доступ к тексту без изменения всех моих XML-файлов для удаления метки? (Это актуально).

Спасибо!

1 Ответ

0 голосов
/ 15 января 2019

С [Python 3]: xml.etree.ElementTree.Element. текст ( выделение - мое):

Эти атрибуты могут использоваться для хранения дополнительных данных, связанных с элементом. Их значения обычно являются строками, но могут быть любыми объектами, специфичными для приложения . Если элемент создается из файла XML, атрибут text содержит либо текст между начальным тегом элемента и его первым дочерним или конечным тегом, либо None и tail атрибут содержит либо текст между конечным тегом элемента и следующим тегом, либо None.

...

Чтобы собрать внутренний текст элемента, см. itertext () , например "".join(element.itertext()).

Я создал 3 файла, основываясь на вашей спецификации:

  • file0.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <foo>
        <bar>
          <info id="1">SampleTextHere 0</info>
        </bar>
      </foo>
    </root>
    
  • file1.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <foo>
        <bar>
          <info id="1"><label>LabelText</label>SampleTextHere 1</info>
        </bar>
      </foo>
    </root>
    
  • file2.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
      <foo>
        <bar>
          <info id="1"></info>
        </bar>
      </foo>
    </root>
    

и пример кода.

code.py

#!/usr/bin/env python3

import sys
import xml.etree.ElementTree as ET


def main():
    file_names = [
        "file0.xml",
        "file1.xml",
        "file2.xml",
    ]

    for file_name in file_names:
        root = ET.parse(file_name).getroot()
        info_node = root.find("foo").find("bar").find("info")
        text = info_node.text
        tail = info_node.tail
        iter_text = "".join(info_node.itertext())
        info_node_text = text or ""
        if not info_node_text:
            for info_node_text in info_node.itertext():
                pass
        print("\n{:s}\n      Text (for debugging purposes): [{:}]\n      Tail (for debugging purposes): [{:}]\n      Iter text (for debugging purposes): [{:s}]\n  Value: [{:s}]".format(
            file_name, text, tail, iter_text, info_node_text))


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main() 

Алгоритм прост: если у узла не установлен атрибут text , выполните итерацию по его itertext() и выберите последнее значение в качестве метки (или любого другого другое) подузел предшествует тексту.

выход

(py_064_03.06.08_test0) e:\Work\Dev\StackOverflow\q054197111>"e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe" code.py
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32


file0.xml
      Text (for debugging purposes): [SampleTextHere 0]
      Tail (for debugging purposes): [
    ]
      Iter text (for debugging purposes): [SampleTextHere 0]
  Value: [SampleTextHere 0]

file1.xml
      Text (for debugging purposes): [None]
      Tail (for debugging purposes): [
    ]
      Iter text (for debugging purposes): [LabelTextSampleTextHere 1]
  Value: [SampleTextHere 1]

file2.xml
      Text (for debugging purposes): [None]
      Tail (for debugging purposes): [
    ]
      Iter text (for debugging purposes): []
  Value: []
...