[英]Remove special characters from keys of a parsed xml file using xmltodict
我使用xmltodict
模塊解析了一個 xml 文件,結果存儲在字典中。
現在我想刪除字典每個鍵中的特殊字符@
和#
。
def remove_using_json(parse_result):
data = {}
data = json.dumps(parse_result)
#print data
#for d in data:
for key, value in data.iterkeys():
if key[0] == '@':
data[key]=key.strip("@")
elif key[0] == '#':
data[key] =key.strip("#")
您不應從回復中刪除這些特殊字符。
有一個選項是根本不讓它們出現在您的回復中。 ;-)
result = xmltodict.parse(response, attr_prefix='@', cdata_key='#text')
這些是默認選項,但您可以設置attr_prefix=""
以去除@
符號,並以相同的方式更改cdata_key
。
此外,如果您不想使用xmltodict.unparse()
將其轉換回 XML,您還可以添加dict_constructor=dict
以在解析的響應中創建字典而不是 OrderDicts。
在解析過程中沒有直接的方法來消除這些,因為它們用於表示屬性和文本節點,允許將它們與元素區分開來(如果它們不存在,則輸出將無法使用)。
例如
xmltodict.parse("""
<root>
<abc><def>ab</def></abc>
<abc id="a3">efg</abc>
</root>
""")
生成具有結構的嵌套有序字典
{'root': {'abc': [
{'def': 'ab'},
{'@id': 'a3', '#text': 'efg'}
]
}
}
@符號告訴我@id是一個屬性。 沒有那個符號,我無法判斷它是一個名為id的屬性還是一個元素。 同樣, #符號告訴我#text是該元素的文本值。 沒有它,我無法判斷它是元素的文本,還是名為text的元素。
但是,在處理密鑰時,您可以使用ky[1:]
剝離它們,其中ky
是密鑰。
例如,如果我將上面解析的輸出分配給變量doc
,我可以做1
for abcelem in doc["root"]["abc"]:
for ky in abcelem:
if ky[0]=="@": print("Attribute:",ky[1:])
elif ky[0]=="#": print("Text Content")
else: print("Element:",ky)
哪個會輸出
Element: def
Attribute: id
Text Content
我從屬性中去除了@符號。
def remover(x): if isinstance(x,list): return [remover(y) for y in x] elif isinstance(x,OrderedDict): for ky in list(x.keys()): if ky[0] in ["@","#"]: x[ky[1:]] = remover(x[ky]) del x[ky] else: x[ky] = remover(x[ky]) return x else: return x
因此,在上面, remover(doc)
將從鍵中刪除所有@和#符號。 如果任何節點具有相同名稱的元素和屬性或名為text的元素或屬性,則行為可能不穩定並且會丟失一些數據,這正是這些符號首先存在的原因。 該函數確實修改了對象,因此,如果需要保留原始對象,則應進行深度復制並將其傳遞給該函數。
from __future__ import print_function
或將打印函數調用更改為類似print "Attribute: "+ky[1:]
語句。
要從字典的鍵中刪除@
,請使用attr_prefix=''
作為 xmltodict.parse() 函數的參數。 要從字典的鍵中刪除#
使用cdata_key='text'
作為xmltodict.parse()
函數的參數。
節點的文本值可以用 python dict 中的
cdata_key
鍵指定,而節點屬性可以用 python dict 中鍵名前綴的attr_prefix
指定。 為默認值attr_prefix
是@
和默認值cdata_key
是#text
。
單擊此處了解詳細信息。
發生這種情況是因為您的功能沒有“深入”。 因此,讓我們從@Matthew 的答案中獲取示例字典,例如:
d = xmltodict.parse("""
<root>
<abc><def>ab</def></abc>
<abc id="a3">efg</abc>
</root>
""")
In [29]: d
Out[29]: {'root': {'abc': [{'def': 'ab'}, {'#text': 'efg', '@id': 'a3'}]}}
您的函數將在此 dict 中僅找到一個鍵: root
。 但是您可以以如下方式遞歸迭代所有項目:
# What if you use different from dict Mapping implementation
# ...like OrderedDict or defaultdict? So lets check type
# ...of the nested 'dicts' with Mapping interface
from collections import Mapping
def transform(element, strip_chars="#@"):
if isinstance(element, Mapping):
return {key.strip(strip_chars): transform(value)
for key, value
in element.iteritems()}
elif isinstance(element, list):
return [transform(item) for item in element]
else:
return element
In [27]: d1 = transform(d)
In [28]: d, d1
Out[28]:
({'root': {'abc': [{'def': 'ab'}, {'#text': 'efg', '@id': 'a3'}]}},
{'root': {'abc': [{'def': 'ab'}, {'id': 'a3', 'text': 'efg'}]}})
import xmltodict
result = xmltodict.parse(xml, attr_prefix="")
將所有@
替換為空字符串
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.