簡體   English   中英

使用 xmltodict 從解析的 xml 文件的鍵中刪除特殊字符

[英]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的元素或屬性,則行為可能不穩定並且會丟失一些數據,這正是這些符號首先存在的原因。 該函數確實修改了對象,因此,如果需要保留原始對象,則應進行深度復制並將其傳遞給該函數。


1這使用 python 3 語法,其中打印命令是一個函數。 要使此示例在 python 2.6 或 2.7 中工作,首先發出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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM