如何使用Python从XML中删除元素

时间:2010-08-29 01:38:43

标签: python xml

我遇到了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:添加了unicode字符和命名空间属性。

UPDATE2:使用Python 2.5,首选标准库。

3 个答案:

答案 0 :(得分:10)

使用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))

产量

<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>

答案 1 :(得分:5)

我不确定如何最好地删除lang属性,但是这里有一些代码可以执行其他更改(Python 2.7;对于2.5或2.6,使用getIterator而不是{{1} }),假设当你删除一个元素时,你也总是希望删除该元素中包含的所有内容。

此代码只是将结果打印到标准输出(您可以根据需要重定向,或者直接将其写入某个新文件,依此类推):

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

答案 2 :(得分:1)

更新@Alex Martelli的代码,以删除元素列表更新到位的错误。如果输入稍微复杂,上述解决方案将给出错误答案。

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

第7行for subelement in element:中的代码更改为for subelement in element[:]:,因为在迭代时更新列表不正确。

此代码迭代元素列表的副本,并在lang时删除元素!=&#34; en&#34;在原始元素列表中。