【发布时间】:2019-07-26 17:45:02
【问题描述】:
我有大量的 XML 数据集 (2-40GB)。一些数据是机密的,所以我正在尝试编辑数据集以屏蔽所有机密信息。我有一长串需要屏蔽的每个值,例如,如果我有 ID 'GYT-1064',我需要查找并替换它的每个实例。这些值可以位于不同的字段/级别/子类中,因此在一个对象中它可能具有“Order-ID = GYT-1064”,而另一个可能会显示“PO-Name = GYT-1064”。我已经研究了 iterparse,但无法弄清楚如何就地编辑 xml 文件而不是在内存中构建整个新树,因为我必须多次遍历它才能找到每个 ID 的每个实例。
理想的功能:
对于每个元素,如果给定的字符串在元素中,则替换文本并更改 XML 文件中的行。
如果数据集足够小以加载到内存中,我有一个可行的解决方案,但我不知道如何正确利用 iterparse。我还研究了所有关于 lxml iterparse 的答案,但是由于我需要多次遍历整个文件,所以我需要能够就地编辑它
有效的简单版本,但必须将整个 xml 加载到内存中(并且不是就地)
values_to_mask = ['val1', 'GMX-103', 'etc-555'] #imported list of vals to mask
with open(dataset_name, encoding='utf8') as f:
tree = ET.parse(f)
root = tree.getroot()
for old in values_to_mask:
new = mu.generateNew(old, randomnumber) #utility to generate new amt
for elem in root.iter():
try:
elem.text = elem.text.replace(old, new)
except AttributeError:
pass
tree.write(output_name, encoding='utf8')
我对 iterparse 的尝试:
with open(output_name, mode='rb+') as f:
context = etree.iterparse( f )
for old in values_to_mask:
new = mu.generateNew(old, randomnumber)
mu.fast_iter(context, mu.replace_if_exists, old, new, f)
def replace_if_exists(elem, old, new, xf):
try:
if(old in elem.text):
elem.text = elem.text.replace(old, new)
xf.write(elem)
except AttributeError:
pass
它运行但不替换任何文本,我得到 print(context.root) = 'Null'。此外,它似乎不会正确地写回原位文件。
XML 数据的基本外观(带有子类的分层对象)
一般是这样的:
<Master_Data_Object>
<Package>
<PackageNr>1000</PackageNr>
<Quantity>900</Quantity>
<ID>FAKE_CONFIDENTIALGYO421</ID>
<Item_subclass>
<ItemType>C</ItemType>
<MasterPackageID>FAKE_CONFIDENTIALGYO421</MasterPackageID>
<Package>
<Other_Types>
【问题讨论】:
-
更新了帖子以显示一些 XML 数据
-
这是将 XML 转换为
pandas数据框的可靠演练,此时过滤数据集和应用掩码非常有效:medium.com/@robertopreste/…