首页 > 解决方案 > 从 XML 中删除重复元素

问题描述

在我来到这里之前,我已经搜索了类似的可能问题来帮助我,但是没有一个能解决我的问题。

我有一个包含电影信息的 xml 文件。我想要的是删除<title>. 波纹管有一些部分的xml:

<imdb>
<movie>
 <title>Alexander and the Terrible, Horrible, No Good, Very Bad Day</title>
 <production_year>2009</production_year>
 <producer>Moritz, Neal H.</producer>
 <distributor>Columbia Pictures [us]</distributor>
 <distributor>Columbia Pictures [us]</distributor>
</movie>
<movie>
 <title>Blood and Donuts</title>
 <production_year>2000</production_year>
 <actor>Kauffmann, Matthew</actor>
 <actor>Benedetto, Marisa</actor>
 <producer>Schwarz, Jeffrey</producer>
 <director>Schwarz, Jeffrey</director>
</movie>
<movie>
 <title>Alexander and the Terrible, Horrible, No Good, Very Bad Day</title>
 <production_year>2009</production_year>
 <producer>Moritz, Neal H.</producer>
 <distributor>Columbia Pictures [us]</distributor>
 <distributor>Columbia Pictures [us]</distributor>
</movie>
</imdb>

如您所见,里面有两个“亚历山大与恐怖,可怕,不好,非常糟糕的一天”电影标题。我想删除所有重复的元素(就像这个例子一样,xml 中还有其他元素),最后,创建一个没有重复值的新 xml 文件。

所需的新 xml 应如下所示:

<imdb>
    <movie>
     <title>Alexander and the Terrible, Horrible, No Good, Very Bad Day</title>
     <production_year>2009</production_year>
     <producer>Moritz, Neal H.</producer>
     <distributor>Columbia Pictures [us]</distributor>
     <distributor>Columbia Pictures [us]</distributor>
    </movie>
    <movie>
     <title>Blood and Donuts</title>
     <production_year>2000</production_year>
     <actor>Kauffmann, Matthew</actor>
     <actor>Benedetto, Marisa</actor>
     <producer>Schwarz, Jeffrey</producer>
     <director>Schwarz, Jeffrey</director>
    </movie>
</imdb>

我从这里看到了这个例子Python 从 xml 树中删除了重复的元素,但对我不起作用。我试过的代码不是我的。我做了一些更改来修改我需要的东西,但没有奏效。你们能帮我解决这个问题吗?谢谢您的帮助。

import xml.etree.ElementTree as ET

path = 'imdb.xml'

tree = ET.parse(path)
root = tree.getroot()
prev = None

def elements_equal(e1, e2):
    if type(e1) != type(e2):
        return False
    if e1.tag != e2.tag: return False
    if e1.text != e2.text: return False
    if e1.tail != e2.tail: return False
    if e1.attrib != e2.attrib: return False
    if len(e1) != len(e2): return False
    return all([elements_equal(c1, c2) for c1, c2 in zip(e1, e2)])

for page in root:                     # iterate over pages
    elems_to_remove = []
    for elem in page:
        if elements_equal(elem, prev):
            print("found duplicate: %s" % elem.text)   # equal function works well
            elems_to_remove.append(elem)
            continue
        prev = elem
    for elem_to_remove in elems_to_remove:
        page.remove(elem_to_remove)
# [...]
tree.write("new_imdb.xml")

更新 !

我尝试使用 xslt。它适用于我的示例,但是当我运行整个 imdb.xml 时它不起作用。它不会删除重复的条目。有什么帮助吗?

在此处输入图像描述

那是我使用的代码:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="imdbMovie" match="movie" use="concat(title,' ',production_year)"/>

<xsl:template match="imdb">
    <xsl:copy>
        <xsl:for-each select="movie[count(. | key('imdbMovie',concat(title,' ',production_year))[1]) = 1]">
            <xsl:copy-of select="."/>
        </xsl:for-each>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>

标签: pythonxmlxsltdataset

解决方案


这是一个解决方案。

from simplified_scrapy import SimplifiedDoc, utils, req
xml = '''
<imdb>
<movie>
 <title>Alexander and the Terrible, Horrible, No Good, Very Bad Day</title>
 <production_year>2009</production_year>
 <producer>Moritz, Neal H.</producer>
 <distributor>Columbia Pictures [us]</distributor>
 <distributor>Columbia Pictures [us]</distributor>
</movie>
<movie>
 <title>Blood and Donuts</title>
 <production_year>2000</production_year>
 <actor>Kauffmann, Matthew</actor>
 <actor>Benedetto, Marisa</actor>
 <producer>Schwarz, Jeffrey</producer>
 <director>Schwarz, Jeffrey</director>
</movie>
<movie>
 <title>Alexander and the Terrible, Horrible, No Good, Very Bad Day</title>
 <production_year>2009</production_year>
 <producer>Moritz, Neal H.</producer>
 <distributor>Columbia Pictures [us]</distributor>
 <distributor>Columbia Pictures [us]</distributor>
</movie>
</imdb>
'''
doc = SimplifiedDoc(xml)
movies = doc.selects('movie')
dic = {}
for movie in movies:
  title = movie.title.text
  if dic.get(title): # Use dictionary to remove duplicate
    movie.remove() # Delete duplicate nodes
  else:
    dic[title]=True
print(doc.html)

推荐阅读