Неправильный синтаксический анализ вложенных тегов XML в Python - PullRequest
3 голосов
/ 11 мая 2019

Я работаю с XML-файлами в Python. У меня есть набор данных, содержащий предложения на нескольких языках, и имеет такую ​​структуру:

<corpus>
  <sentence id="0">
    <text lang="de">...</text>
    <text lang="en">...</text>
    <text lang="fr">...</text>
    <!-- Other languages -->
    <annotations>
      <annotation lang="de">...</annotation>
      <annotation lang="en">...</annotation>
      <annotation lang="fr">...</annotation>
      <!-- Other languages -->
    </annotations>
  </sentence>
  <sentence id="1">
    <!-- Other sentence -->
  </sentence>
  <!-- Other sentences -->
</corpus>

Я хочу получить, начиная с набора данных, новый набор данных, содержащий только предложения и аннотации на английском языке ("en" значение атрибута "lang"). Я пробовал это решение:

import xml.etree.ElementTree as ET
tree = ET.parse('samplefile2.xml')
root = tree.getroot()
for sentence in root:
  if sentence.tag == 'sentence':
    for txt in sentence:
      if txt.tag == 'text':
        if txt.attrib['lang'] != 'en':
          sentence.remove(txt)
      if txt.tag == 'annotations':
        for annotation in txt:
          if annotation.attrib['lang'] != 'en':
            txt.remove(annotation)
tree.write('output.xml')

Но, похоже, он работает только на уровне атрибута text, а не на уровне атрибута annotation. Я попытался даже заменить на стороне Python элементы решения, такие как sentence, txt, annotation, с инкрементными индексами root[s], root[s][t], root[s][t][a], но это не дает никакого эффекта. Кроме того, предоставленный мною код python вставляет случайным образом в файл xml (честно говоря, я не знаю, может ли это помочь в решении этой проблемы) строки типа &#948;&#951;&#956;&#953;&#959;&#965;&#961;&#947;&#943;&#945;.

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

1 Ответ

1 голос
/ 11 мая 2019

Если вы можете использовать lxml, я думаю, что было бы проще с помощью xpath ...

Ввод XML (input.xml)

<corpus>
  <sentence id="0">
    <text lang="de">...</text>
    <text lang="en">...</text>
    <text lang="fr">...</text>
    <!-- Other languages -->
    <annotations>
      <annotation lang="de">...</annotation>
      <annotation lang="en">...</annotation>
      <annotation lang="fr">...</annotation>
      <!-- Other languages -->
    </annotations>
  </sentence>
  <sentence id="1">
    <!-- Other sentence -->
  </sentence>
  <!-- Other sentences -->
</corpus>

Python

from lxml import etree

target_lang = "en"

tree = etree.parse("input.xml")

# Match any element that has a child that has a lang attribute with a value other than
# target_lang. We need this element so we can remove the child from it.
for parent in tree.xpath(f".//*[*[@lang != '{target_lang}']]"):
    # Match the children that have a lang attribute with a value other than target_lang.
    for child in parent.xpath(f"*[@lang != '{target_lang}']"):
        # Remove the child from the parent.
        parent.remove(child)

tree.write("output.xml")

Вывод XML (output.xml)

<corpus>
  <sentence id="0">
    <text lang="en">...</text>
    <!-- Other languages -->
    <annotations>
      <annotation lang="en">...</annotation>
      <!-- Other languages -->
    </annotations>
  </sentence>
  <sentence id="1">
    <!-- Other sentence -->
  </sentence>
  <!-- Other sentences -->
</corpus>
...