[英]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.