Как удалить элементы из XML с помощью Python

Я застрял с XML и Python. Задача проста, но я так и не смог ее решить и потратил столько времени. Я пришел сюда за советом, как решить эту проблему с помощью нескольких строк.

Спасибо за любую помощь в обходе дерева. Я всегда получал слишком много или слишком мало элементов. Элементы могут быть вложены без ограничений. Данный пример является только примером. Я приму любое решение, не придирчивое к dom, minidom, sax, к чему угодно.

У меня есть XML-файл, похожий на этот:

<root>
    <elm>
        <elm>Common content</elm>

        <elm xmlns="http://example.org/ns">
            <elm lang="en">Content EN</elm>
            <elm lang="cs">žluťoučký koníček</elm>
        </elm>

        <elm xml:id="abc123">Common content</elm>

        <elm lang="en">Content EN</elm>
        <elm lang="cs">Content CS</elm>

        <elm lang="en">
            <elm>Content EN</elm>
            <elm>Content EN</elm>
        </elm>

        <elm lang="cs">
            <elm>Content CS</elm>
            <elm>Content CS</elm>
        </elm>
    </elm>
</root>

Что мне нужно - разобрать XML и написать новый файл. Новый файл должен содержать все элементы для данного языка и элементы без атрибута lang .

Для языка «cs» выходной файл должен содержать это:

<root>
    <elm>
        <elm>Common content</elm>

        <elm xmlns="http://example.org/ns">
            <elm lang="cs">žluťoučký koníček</elm>
        </elm>

        <elm xml:id="abc123">Common content</elm>

        <elm lang="cs">Content CS</elm>

        <elm lang="cs">
            <elm>Content CS</elm>
            <elm>Content CS</elm>
        </elm>
    </elm>
</root>

Если вы можете сделать это, чтобы опустить атрибут lang в новом файле, даже лучше. Но это не так важно.

UPDATE1: Добавлены символы юникода и атрибут пространства имен.

UPDATE2: Использование Python 2.5, предпочтительнее для стандартных библиотек.

9
задан dwich 31 August 2010 в 22:27
поделиться

2 ответа

Использование lxml:

import lxml.etree as le

with open('doc.xml','r') as f:
    doc=le.parse(f)
    for elem in doc.xpath('//*[attribute::lang]'):
        if elem.attrib['lang']=='en':
            elem.attrib.pop('lang')
        else:
            parent=elem.getparent()
            parent.remove(elem)
    print(le.tostring(doc))

yields

<root>
    <elm>Common content</elm>

    <elm>
        <elm>Content EN</elm>
        </elm>

    <elm>Common content</elm>

    <elm>Content EN</elm>
    <elm>
        <elm>Content EN</elm>
        <elm>Content EN</elm>
    </elm>

    </root>
10
ответ дан 4 December 2019 в 12:16
поделиться

Я не уверен, как лучше всего удалить атрибут lang, но вот код, который выполняет другие изменения (Python 2.7; для 2.5 или 2.6 используйте getIterator вместо iter), предполагая, что при удалении элемента вы также всегда хотите удалить все, что содержится в этом элементе.

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

import sys
from xml.etree import cElementTree as et

def picklang(path, lang='en'):
    tr = et.parse(path)
    for element in tr.iter():
        for subelement in element:
            la = subelement.get('lang')
            if la is not None and la != lang:
                element.remove(subelement)
    return tr

if __name__ == '__main__':
    tr = picklang('la.xml')
    tr.write(sys.stdout)
    print

С la.xml в вашем примере это пишет

<root>
    <elm>Common content</elm>

    <elm>
        <elm lang="en">Content EN</elm>
        </elm>

    <elm>Common content</elm>

    <elm lang="en">Content EN</elm>
    <elm lang="en">
        <elm>Content EN</elm>
        <elm>Content EN</elm>
    </elm>

    </root>
6
ответ дан 4 December 2019 в 12:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: