Python中將字典轉(zhuǎn)換為XML以及相關(guān)的命名空間解析
盡管 xml.etree.ElementTree 庫通常用來做解析工作,其實(shí)它也可以創(chuàng)建XML文檔。 例如,考慮如下這個(gè)函數(shù):
from xml.etree.ElementTree import Element def dict_to_xml(tag, d): ''' Turn a simple dict of key/value pairs into XML ''' elem = Element(tag) for key, val in d.items(): child = Element(key) child.text = str(val) elem.append(child) return elem
下面是一個(gè)使用例子:
>>> s = { 'name': 'GOOG', 'shares': 100, 'price':490.1 }
>>> e = dict_to_xml('stock', s)
>>> e
<Element 'stock' at 0x1004b64c8>
>>>
轉(zhuǎn)換結(jié)果是一個(gè) Element 實(shí)例。對于I/O操作,使用 xml.etree.ElementTree 中的 tostring() 函數(shù)很容易就能將它轉(zhuǎn)換成一個(gè)字節(jié)字符串。例如:
>>> from xml.etree.ElementTree import tostring >>> tostring(e) b'<stock><price>490.1</price><shares>100</shares><name>GOOG</name></stock>' >>>
如果你想給某個(gè)元素添加屬性值,可以使用 set() 方法:
>>> e.set('_id','1234')
>>> tostring(e)
b'<stock _id="1234"><price>490.1</price><shares>100</shares><name>GOOG</name>
</stock>'
>>>
如果你還想保持元素的順序,可以考慮構(gòu)造一個(gè) OrderedDict 來代替一個(gè)普通的字典。當(dāng)創(chuàng)建XML的時(shí)候,你被限制只能構(gòu)造字符串類型的值。例如:
def dict_to_xml_str(tag, d):
'''
Turn a simple dict of key/value pairs into XML
'''
parts = ['<{}>'.format(tag)]
for key, val in d.items():
parts.append('<{0}>{1}</{0}>'.format(key,val))
parts.append('</{}>'.format(tag))
return ''.join(parts)
問題是如果你手動的去構(gòu)造的時(shí)候可能會碰到一些麻煩。例如,當(dāng)字典的值中包含一些特殊字符的時(shí)候會怎樣呢?
>>> d = { 'name' : '<spam>' }
>>> # String creation
>>> dict_to_xml_str('item',d)
'<item><name><spam></name></item>'
>>> # Proper XML creation
>>> e = dict_to_xml('item',d)
>>> tostring(e)
b'<item><name><spam></name></item>'
>>>
注意到程序的后面那個(gè)例子中,字符 ‘<' 和 ‘>' 被替換成了 < 和 >
下面僅供參考,如果你需要手動去轉(zhuǎn)換這些字符, 可以使用 xml.sax.saxutils 中的 escape() 和 unescape() 函數(shù)。例如:
>>> from xml.sax.saxutils import escape, unescape
>>> escape('<spam>')
'<spam>'
>>> unescape(_)
'<spam>'
>>>
除了能創(chuàng)建正確的輸出外,還有另外一個(gè)原因推薦你創(chuàng)建 Element 實(shí)例而不是字符串, 那就是使用字符串組合構(gòu)造一個(gè)更大的文檔并不是那么容易。 而 Element 實(shí)例可以不用考慮解析XML文本的情況下通過多種方式被處理。 也就是說,你可以在一個(gè)高級數(shù)據(jù)結(jié)構(gòu)上完成你所有的操作,并在最后以字符串的形式將其輸出。
利用命名空間解析XML文檔
如果你解析這個(gè)文檔并執(zhí)行普通的查詢,你會發(fā)現(xiàn)這個(gè)并不是那么容易,因?yàn)樗胁襟E都變得相當(dāng)?shù)姆爆崱?/p>
>>> # Some queries that work
>>> doc.findtext('author')
'David Beazley'
>>> doc.find('content')
<Element 'content' at 0x100776ec0>
>>> # A query involving a namespace (doesn't work)
>>> doc.find('content/html')
>>> # Works if fully qualified
>>> doc.find('content/{http://www.w3.org/1999/xhtml}html')
<Element '{http://www.w3.org/1999/xhtml}html' at 0x1007767e0>
>>> # Doesn't work
>>> doc.findtext('content/{http://www.w3.org/1999/xhtml}html/head/title')
>>> # Fully qualified
>>> doc.findtext('content/{http://www.w3.org/1999/xhtml}html/'
... '{http://www.w3.org/1999/xhtml}head/{http://www.w3.org/1999/xhtml}title')
'Hello World'
>>>
你可以通過將命名空間處理邏輯包裝為一個(gè)工具類來簡化這個(gè)過程:
class XMLNamespaces:
def __init__(self, **kwargs):
self.namespaces = {}
for name, uri in kwargs.items():
self.register(name, uri)
def register(self, name, uri):
self.namespaces[name] = '{'+uri+'}'
def __call__(self, path):
return path.format_map(self.namespaces)
通過下面的方式使用這個(gè)類:
>>> ns = XMLNamespaces(html='http://www.w3.org/1999/xhtml')
>>> doc.find(ns('content/{html}html'))
<Element '{http://www.w3.org/1999/xhtml}html' at 0x1007767e0>
>>> doc.findtext(ns('content/{html}html/{html}head/{html}title'))
'Hello World'
>>>
討論
解析含有命名空間的XML文檔會比較繁瑣。 上面的 XMLNamespaces 僅僅是允許你使用縮略名代替完整的URI將其變得稍微簡潔一點(diǎn)。
很不幸的是,在基本的 ElementTree 解析中沒有任何途徑獲取命名空間的信息。 但是,如果你使用 iterparse() 函數(shù)的話就可以獲取更多關(guān)于命名空間處理范圍的信息。例如:
>>> from xml.etree.ElementTree import iterparse
>>> for evt, elem in iterparse('ns2.xml', ('end', 'start-ns', 'end-ns')):
... print(evt, elem)
...
end <Element 'author' at 0x10110de10>
start-ns ('', 'http://www.w3.org/1999/xhtml')
end <Element '{http://www.w3.org/1999/xhtml}title' at 0x1011131b0>
end <Element '{http://www.w3.org/1999/xhtml}head' at 0x1011130a8>
end <Element '{http://www.w3.org/1999/xhtml}h1' at 0x101113310>
end <Element '{http://www.w3.org/1999/xhtml}body' at 0x101113260>
end <Element '{http://www.w3.org/1999/xhtml}html' at 0x10110df70>
end-ns None
end <Element 'content' at 0x10110de68>
end <Element 'top' at 0x10110dd60>
>>> elem # This is the topmost element
<Element 'top' at 0x10110dd60>
>>>
最后一點(diǎn),如果你要處理的XML文本除了要使用到其他高級XML特性外,還要使用到命名空間, 建議你最好是使用 lxml 函數(shù)庫來代替 ElementTree 。 例如,lxml 對利用DTD驗(yàn)證文檔、更好的XPath支持和一些其他高級XML特性等都提供了更好的支持。 這一小節(jié)其實(shí)只是教你如何讓XML解析稍微簡單一點(diǎn)。
相關(guān)文章
pytorch人工智能之torch.gather算子用法示例
這篇文章主要介紹了pytorch人工智能之torch.gather算子用法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
Python3實(shí)現(xiàn)獲取圖片文字里中文的方法分析
這篇文章主要介紹了Python3實(shí)現(xiàn)獲取圖片文字里中文的方法,結(jié)合實(shí)例形式分析了Python基于文字識別引擎tesseract-ocr針對圖片里中文識別的相關(guān)操作技巧與操作注意事項(xiàng),需要的朋友可以參考下2018-12-12
Python實(shí)現(xiàn)生活常識解答機(jī)器人
今天教大家如何用Python爬蟲去搭建一個(gè)「生活常識解答」機(jī)器人.思路:這個(gè)機(jī)器人主要是依托于“阿里達(dá)摩院發(fā)布的語言模型PLUG”,通過爬蟲的方式,發(fā)送post請求(提問),然后返回json數(shù)據(jù)(回答),需要的朋友可以參考下2021-06-06
Django admin 實(shí)現(xiàn)search_fields精確查詢實(shí)例
這篇文章主要介紹了Django admin 實(shí)現(xiàn)search_fields精確查詢實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Python for Informatics 第11章之正則表達(dá)式(二)
這篇文章主要介紹了Python for Informatics 第11章 正則表達(dá)式(二)的相關(guān)資料,需要的朋友可以參考下2016-04-04
Python數(shù)據(jù)分析之雙色球統(tǒng)計(jì)單個(gè)紅和藍(lán)球哪個(gè)比例高的方法
這篇文章主要介紹了Python數(shù)據(jù)分析之雙色球統(tǒng)計(jì)單個(gè)紅和藍(lán)球哪個(gè)比例高的方法,涉及Python數(shù)值運(yùn)算及圖形繪制相關(guān)操作技巧,需要的朋友可以參考下2018-02-02

