在解析过程中没有直接的方法来消除它们,因为它们用于表示属性和文本节点,从而可以将它们与元素区分开来(如果它们不存在,则输出将无法使用)。
例如
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:]
where ky
is key 来剥离它们。
例如,如果我将上面解析的输出分配给变量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 函数调用更改为语句,如
print "Attribute: "+ky[1:]
.