我使用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("#")
答案 0 :(得分:5)
您不应该从回复中删除这些特殊字符。
可以选择不让它们进入您的回复。 ; - )
result = xmltodict.parse(response, attr_prefix='@', cdata_key='#text')
这些是默认选项,但您可以设置attr_prefix=''
以删除@
符号,并以相同方式更改cdata_key
。
P.S。此外,您还可以使用dict_constructor=dict
在已解析的响应中创建字典而不是OrderDicts,例如,如果您不能使用xmltodict.unparse()
将其转换回XML。
答案 1 :(得分:2)
在解析过程中没有直接的方法来消除它们,因为它们用于表示属性和文本节点,允许它们与元素区分开(如果它们不存在输出将无法使用)。
例如
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 的元素或属性,则会丢失一些数据,这正是为什么这些符号首先出现在那里的原因。此函数确实修改了对象,因此,如果需要保留原始对象,则应进行深度复制并将其传递给函数。
<小时/> 1 这使用python 3语法,其中print命令是一个函数。要使此示例在python 2.6或2.7中工作,请首先发出
from __future__ import print_function
或将打印函数调用更改为print "Attribute: "+ky[1:]
之类的语句。
答案 2 :(得分:1)
之所以发生这种情况,是因为您的功能无法深入了解。因此,让我们从@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'}]}}
您的函数只会在此词典中找到一个键: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'}]}})
答案 3 :(得分:0)
要从字典键中删除@
,请使用attr_prefix=''
作为xmltodict.parse()函数的参数。
要从字典键中删除#
,请使用cdata_key='text'
作为xmltodict.parse()
函数的参数。
节点的文本值可以使用python dict中的
cdata_key
键指定,而节点属性可以使用python dict中的键名前缀attr_prefix
来指定。attr_prefix
的默认值为@
,cdata_key
的默认值为#text
。
单击here了解详情。