gpt4 book ai didi

Python XML 删除一些元素及其子元素但保留特定元素及其子元素

转载 作者:太空宇宙 更新时间:2023-11-04 01:29:13 25 4
gpt4 key购买 nike

我有一个非常大的 .xml 文件,我正在尝试创建一个新的 .xml 文件,它只包含这个较大文件内容的一小部分。我想指定一个属性(在我的例子中,一个 itemID)并给它一些特定的值,然后它会去除所有元素,除了那些具有这些 itemID 及其子元素的元素。

我的大型 .xml 文件看起来像这样:

<?xml version='1.0' encoding='UTF-8'?>
<api version="2">
<currentTime>2013-02-27 17:00:18</currentTime>
<result>
<rowset name="assets" key="itemID" columns="itemID,locationID,typeID,quantity,flag,singleton">
<row itemID="1008551770576" locationID="31000559" typeID="17187" quantity="1" flag="0" singleton="1" rawQuantity="-1" />
<row itemID="1008700753886" locationID="31000559" typeID="17187" quantity="1" flag="0" singleton="1" rawQuantity="-1" />
<row itemID="1008700756994" locationID="31000559" typeID="17184" quantity="1" flag="0" singleton="1" rawQuantity="-1" />
<row itemID="1008701224901" locationID="31000559" typeID="17186" quantity="1" flag="0" singleton="1" rawQuantity="-1" />
<row itemID="1004072840841" locationID="31002238" typeID="17621" quantity="1" flag="0" singleton="1" rawQuantity="-1">
<rowset name="contents" key="itemID" columns="itemID,typeID,quantity,flag,singleton">
<row itemID="150571923" typeID="25863" quantity="2" flag="119" singleton="0" />
<row itemID="188435728" typeID="3388" quantity="1" flag="119" singleton="0" />
<row itemID="210122947" typeID="3419" quantity="4" flag="119" singleton="0" />
</rowset>
</row>
<row itemID="1005279202146" locationID="31002238" typeID="17621" quantity="1" flag="0" singleton="1" rawQuantity="-1">
<rowset name="contents" key="itemID" columns="itemID,typeID,quantity,flag,singleton">
<row itemID="1004239962001" typeID="16275" quantity="49596" flag="4" singleton="0" />
<row itemID="1005364142068" typeID="4246" quantity="156929" flag="4" singleton="0" />
<row itemID="1005624252854" typeID="4247" quantity="93313" flag="4" singleton="0" />
</rowset>
</row>
<row itemID="1004388226389" typeID="648" quantity="1" flag="0" singleton="1" rawQuantity="-1">
<rowset name="contents" key="itemID" columns="itemID,typeID,quantity,flag,singleton">
<row itemID="1004388228218" typeID="31119" quantity="1" flag="92" singleton="1" rawQuantity="-1" />
<row itemID="1004388701243" typeID="31119" quantity="1" flag="94" singleton="1" rawQuantity="-1" />
<row itemID="1004388701485" typeID="31119" quantity="1" flag="93" singleton="1" rawQuantity="-1" />
<row itemID="1009147502645" typeID="51" quantity="1" flag="5" singleton="1" rawQuantity="-1" />
</rowset>
</row>
</rowset>
</result>
<cachedUntil>2013-02-27 23:00:18</cachedUntil>
</api>

这个文件大约有九万行,大约 9 兆字节。

请注意 itemID 是如何存在的,某些项目类型可以(但不总是)在其中包含更多项目,并且这些子项也有自己的 itemID。我正在尝试获取一些特定的 itemID 及其子项,而忽略所有其他项。

我使用了 this answer 中的代码这让我很接近。它是完美的,除了它遗漏了我使用的 itemID 的 child 。

我的代码是这样的:

import lxml.etree as le

##Take this big .xml file and pull out just the parts we want then write those to a new .xml file##
with open(filename,'r') as f:
doc=le.parse(f)
for elem in doc.xpath('//*[attribute::itemID]'):
if elem.attrib['itemID']=='1004072840841':
elem.attrib.pop('itemID')
else:
parent=elem.getparent()
parent.remove(elem)
print(le.tostring(doc))

打印结果如下:

<api version="2">
<currentTime>2013-03-01 21:46:52</currentTime>
<result>
<rowset name="assets" key="itemID" columns="itemID,locationID,typeID,quantity,flag,singleton">
<row locationID="31002238" typeID="17621" quantity="1" flag="0" singleton="1" rawQuantity="-1">
<rowset name="contents" key="itemID" columns="itemID,typeID,quantity,flag,singleton">
</rowset>
</row>
</rowset>
</result>
<cachedUntil>2013-03-02 03:46:53</cachedUntil>
</api>

我希望它看起来像这样:

<api version="2">
<currentTime>2013-03-01 21:46:52</currentTime>
<result>
<rowset name="assets" key="itemID" columns="itemID,locationID,typeID,quantity,flag,singleton">
<row locationID="31002238" typeID="17621" quantity="1" flag="0" singleton="1" rawQuantity="-1">
<rowset name="contents" key="itemID" columns="itemID,typeID,quantity,flag,singleton">
<row itemID="150571923" typeID="25863" quantity="2" flag="119" singleton="0" />
<row itemID="188435728" typeID="3388" quantity="1" flag="119" singleton="0" />
<row itemID="210122947" typeID="3419" quantity="4" flag="119" singleton="0" />
</rowset>
</row>
</rowset>
</result>
<cachedUntil>2013-03-02 03:46:53</cachedUntil>
</api>

我对代码的理解还不够深入,看不出我需要更改哪些内容才能同时包含我让它搜索的 itemID 的子项。此外,理想情况下,我能够放入多个 itemID,它会去除除那些 itemID 及其子项之外的所有项。这意味着它需要保留 itemID=[number] 行属性(以便我在使用此 xml 文件时可以使用 xPath 来引用特定的 itemID 及其子项。)

所以我的主要问题是关于如何在生成的 .xml 中包含我搜索的 itemID 的子项。我的第二个问题是关于如何同时对多个 itemID 执行此操作(这样生成的 .xml 文件将删除除那些 itemID 及其子项之外的所有内容。)

更新:丑陋的解决方案

我发现 elem.attrib.pop('itemID') 部分是取出 itemID 的部分,因为我想要多个 itemIDs 并且他们的 child 仍然存在,所以我需要为了保留这个,所以我把那个部分去掉了。我试图找到一种方法来跳过带有我正在搜索的 itemID 的行的子项,而我想到的是用一个属性标记每个子项,然后我可以重新搜索并删除所有不存在的属性有那个属性。我不需要 flag 属性来完成我正在做的事情,所以我继续使用它来达到这个目的(因为当我试图迭代它们时,尝试引入一个新属性遇到了一个关键错误。)只是标记 children 还不够,我还得标记 children 的 child 。

这是我丑陋的解决方案:

with open(filename,'r') as f:
doc=le.parse(f)
for elem in doc.xpath('//*[attribute::itemID]'):
if elem.attrib['itemID']=='1004072840841' or elem.attrib['itemID']=='1005279202146': # this or statement lets me get a resulting .xml file that has two itemIDs and their children
elem.attrib['flag']='Keep'
for child in elem.iterchildren():
child.attrib['flag']='Keep'
for c in child.iterchildren():
c.attrib['flag']='Keep'
else:
pass
for e in doc.xpath('//*[attribute::flag]'):
if e.attrib['flag']!='Keep':
parent=e.getparent()
parent.remove(e)
else:
pass
print(le.tostring(doc))
##This part writes the pruned down .xml to a file##
with open('test.xml', 'w') as t:
for line in le.tostring(doc):
t.write(line)
t.close

这个丑陋的解决方案涉及对数据进行大量迭代,我怀疑这远非完成此任务的最有效方法,但它确实有效。

最佳答案

你不是很清楚你到底在追求什么,但这段代码会产生你说你想要的输出:

from lxml import etree as ET

def filter_by_itemid(doc, idlist):
rowset = doc.xpath("/api/result/rowset[@name='assets']")[0]
for elem in rowset.getchildren():
if int(elem.get("itemID")) not in idlist:
rowset.remove(elem)
return doc

doc = ET.parse("test.xml")
filter_by_itemid(doc, [1004072840841])

print(ET.tostring(doc))

关于Python XML 删除一些元素及其子元素但保留特定元素及其子元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15168259/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com