【问题标题】:Not parsing correctly nested xml tags in python未在 python 中正确解析嵌套的 xml 标签
【发布时间】:2019-05-10 21:50:34
【问题描述】:

我在 python 中处理 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>

我想要得到的是,从数据集开始,一个新的数据集只包含英语句子和注释(属性“lang”的“en”值)。我试过这个解决方案:

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 属性的级别。我什至尝试用增量索引root[s], root[s][t], root[s][t][a] 替换解决方案元素的python 端,如sentence, txt, annotation,但排序没有效果。此外,我提供的 python 代码在 xml 文件中随机插入(老实说我不知道​​这是否有助于解决这个问题)字符串,如&amp;#948;&amp;#951;&amp;#956;&amp;#953;&amp;#959;&amp;#965;&amp;#961;&amp;#947;&amp;#943;&amp;#945;

所以,我坚信问题出在嵌套标签上,但我无法弄清楚。有什么想法吗?

【问题讨论】:

  • 你能用 lxml 代替 ElementTree 吗?我认为使用 xpath 会容易得多。
  • 没想到,我去试试!
  • 我会继续添加一个 lxml 答案;如果你需要一个例子。

标签: python xml lxml elementtree


【解决方案1】:

如果你能够使用 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>

【讨论】:

  • 难以置信的简单和魅力!我不知道 lxml,因为在今天之前我从未在 python 中解析过 xml 文件。非常感谢!
猜你喜欢
  • 2011-09-24
  • 1970-01-01
  • 1970-01-01
  • 2011-01-30
  • 1970-01-01
  • 2020-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多