2

我已经使用该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("#")
4

4 回答 4

14

您不应该从您的回复中删除这些特殊字符。

可以选择根本不让他们出现在您的回复中。;-)

result = xmltodict.parse(response, attr_prefix='@', cdata_key='#text')

这些是默认选项,但您可以设置attr_prefix=""摆脱@符号,并cdata_key以相同的方式进行更改。

此外,dict_constructor=dict如果您不想使用xmltodict.unparse().

于 2017-07-10T09:54:06.657 回答
3

@从字典的键中删除attr_prefix=''用作 xmltodict.parse() 函数的参数。#从字典的键中删除cdata_key='text'用作函数的参数xmltodict.parse()

节点的文本值可以用cdata_keypython dict 中的键指定,而节点属性可以用attr_prefixpython dict 中键名的前缀指定。is的默认值和attr_prefixis@的默认值。cdata_key#text

点击这里了解详情。

于 2019-02-06T10:04:15.140 回答
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:]where kyis 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:].

于 2016-02-17T09:53:16.913 回答
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'}]}}

您的函数将在此 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'}]}})
于 2016-02-17T11:36:07.930 回答