【问题标题】:Check and remove duplicated children tags in XML检查并删除 XML 中重复的子标签
【发布时间】:2016-09-02 12:57:06
【问题描述】:

我正在通过 Python 中的 Element Tree 解析一个类似 XML 的文件,并将内容写入 pandas 数据框。

我目前面临以下问题:子标签的存在会因不同的标签而异。对于here 提到的解决方案,这不是问题。然而,复杂的部分是一些标签有重复的子标签,而另一些则没有。例如,第一个产品标签有两个(不同的)商品编号和两个相等的 product_types(重复),而第二个产品标签只有一个。

<main>
    <product>
       <article_nr>B00024J7C6</article_nr>
       <article_nr>44253</article_nr>
       <product_type>x</product_type>
       <product_type>x</product_type>
    </product>

    <product>
       <article_nr>B00024J7C7</article_nr>
       <product_type>y</product_type>
    </product>
</main>

我想做的是: 1.) 删除“product_type”的重复项和 2.) 如果不存在第二个 article_nr,则将值设置为 NULL,否则取值。

到目前为止我的代码:

def create_dataframe(data):
    df = pd.DataFrame(columns=('article_nr', 'article_nr2', 'product_type', 'product_type2','product_type2'))
    for i in range(len(data)):
        obj = data.getchildren()[i].getchildren()
        row = dict(itertools.izip(['article_nr', 'article_nr2', 'product_type', 'product_type2','product_type2'], 
                       [obj[0].text, obj[1].text, obj[2].text, obj[3].text, obj[4].text]))
        row_s = pd.Series(row)
        row_s.name = i
        df = df.append(row_s)
    return df

这适用于第一个示例,但显然不适用于第二个示例,因为第二个 'article_nr' 和 'product_type' 没有值。

输出应该是:

article_nr    article_nr    product_type
B00024J7C6    44253           x
B00024J7C7    NULL            y

【问题讨论】:

  • 能否请您添加您目前拥有的代码和所需的输出?谢谢。
  • 那么为什么解析后不能这样做呢?为什么之前需要这样做?
  • 我已经添加了代码和所需的输出@alecxe
  • @e4c5 感谢您的提示。我改了标题,因为解析后这样做也可以,甚至更好。

标签: python xml parsing elementtree


【解决方案1】:

看看Python remove duplicate elements from xml tree,也许对你有帮助。 像这样的东西:

import xml.etree.ElementTree as ET
path = 'in.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 != e1.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("out.xml")

【讨论】:

  • 该代码通过删除所有重复项解决了第一个问题。我自己解决了第二个问题,代码如下:for product in root.findall('product'): article_nr = product.findall('article_nr') if len(article_nr) == 1: product.insert(1, ET.Element('article_nr'))
猜你喜欢
  • 2019-11-15
  • 1970-01-01
  • 2018-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多