Вставка переноса дочернего элемента в lxml - PullRequest
0 голосов
/ 11 октября 2018

Я пытаюсь вставить дочерний элемент в элемент, который будет иметь тот же текст, что и их предыдущий родитель, поэтому дочерний элемент-обертка.Базовый пример, это мой ввод:

<p>
    <s>text</s>
    <s>text</s>
    <s>text</s>
</p>

Я бы хотел что-то вроде этого (содержимое anno получилось бы из инструмента НЛП, не очень важно):

<p>
    <s>
        <orig>text</orig>
        <anno>token1</anno>
    </s>
    <s>
        <orig>text</orig>
        <anno>token2</anno>
    </s>
    <s>
        <orig>text</orig>
        <anno>token3</anno>
    </s>
</p>

Элемент anno был бы проще, но я не могу создать внутри него дочерний элемент, содержащий текст, который раньше имелся.

Используя различные функции элемента (addprevious, addnext, append, insert), я получаюсделать вещи вроде:

    <s>text<orig/></s>
    <s>text<orig>text</orig></s>
    <orig><s>text</s></orig>

Но ничего из этого я не хочу.Должен ли я работать с заменой?И в этом случае как?Спасибо!

1 Ответ

0 голосов
/ 11 октября 2018

Попробуйте:

import sys

from lxml import etree

tree = etree.parse(open("/tmp/so.xml"))

# Make sure you have enough annos to match the existing <s> elements.
annos = ["token1", "token2", "token3"]

for i, s in enumerate(tree.xpath("//s")):
    # remember the text of the <s>
    text = s.text

    # remove the <s> from its parent
    parent = s.getparent()
    parent.remove(s)

    # create a new <s>
    new_s = etree.SubElement(parent, "s")

    # create the <orig>, set the remembered text on it
    orig = etree.SubElement(new_s, "orig")
    orig.text = text

    # create the <anon>, set the token on it
    annon = etree.SubElement(new_s, "anon")
    annon.text = annos[i]

with open("/tmp/out.xml", "wb") as f:
    tree.write(f, pretty_print=True)

Вывод:

<p>
  <s>
    <orig>text</orig>
    <anon>token1</anon>
  </s>
  <s>
    <orig>text</orig>
    <anon>token2</anon>
  </s>
  <s>
    <orig>text</orig>
    <anon>token3</anon>
  </s>
</p>
...