国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python中將字典轉換為XML以及相關的命名空間解析

2019-11-25 17:03:52
字體:
來源:轉載
供稿:網友

盡管 xml.etree.ElementTree 庫通常用來做解析工作,其實它也可以創建XML文檔。 例如,考慮如下這個函數:

from xml.etree.ElementTree import Elementdef 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

下面是一個使用例子:

>>> s = { 'name': 'GOOG', 'shares': 100, 'price':490.1 }>>> e = dict_to_xml('stock', s)>>> e<Element 'stock' at 0x1004b64c8>>>>

轉換結果是一個 Element 實例。對于I/O操作,使用 xml.etree.ElementTree 中的 tostring() 函數很容易就能將它轉換成一個字節字符串。例如:

>>> from xml.etree.ElementTree import tostring>>> tostring(e)b'<stock><price>490.1</price><shares>100</shares><name>GOOG</name></stock>'>>>

如果你想給某個元素添加屬性值,可以使用 set() 方法:

>>> e.set('_id','1234')>>> tostring(e)b'<stock _id="1234"><price>490.1</price><shares>100</shares><name>GOOG</name></stock>'>>>

如果你還想保持元素的順序,可以考慮構造一個 OrderedDict 來代替一個普通的字典。當創建XML的時候,你被限制只能構造字符串類型的值。例如:

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)

問題是如果你手動的去構造的時候可能會碰到一些麻煩。例如,當字典的值中包含一些特殊字符的時候會怎樣呢?

>>> 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>'>>>

注意到程序的后面那個例子中,字符 ‘<' 和 ‘>' 被替換成了 < 和 >

下面僅供參考,如果你需要手動去轉換這些字符, 可以使用 xml.sax.saxutils 中的 escape() 和 unescape() 函數。例如:

>>> from xml.sax.saxutils import escape, unescape>>> escape('<spam>')'<spam>'>>> unescape(_)'<spam>'>>>

除了能創建正確的輸出外,還有另外一個原因推薦你創建 Element 實例而不是字符串, 那就是使用字符串組合構造一個更大的文檔并不是那么容易。 而 Element 實例可以不用考慮解析XML文本的情況下通過多種方式被處理。 也就是說,你可以在一個高級數據結構上完成你所有的操作,并在最后以字符串的形式將其輸出。

利用命名空間解析XML文檔
如果你解析這個文檔并執行普通的查詢,你會發現這個并不是那么容易,因為所有步驟都變得相當的繁瑣。

>>> # 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'>>>

你可以通過將命名空間處理邏輯包裝為一個工具類來簡化這個過程:

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)

通過下面的方式使用這個類:

>>> 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將其變得稍微簡潔一點。

很不幸的是,在基本的 ElementTree 解析中沒有任何途徑獲取命名空間的信息。 但是,如果你使用 iterparse() 函數的話就可以獲取更多關于命名空間處理范圍的信息。例如:

>>> 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 Noneend <Element 'content' at 0x10110de68>end <Element 'top' at 0x10110dd60>>>> elem # This is the topmost element<Element 'top' at 0x10110dd60>>>>

最后一點,如果你要處理的XML文本除了要使用到其他高級XML特性外,還要使用到命名空間, 建議你最好是使用 lxml 函數庫來代替 ElementTree 。 例如,lxml 對利用DTD驗證文檔、更好的XPath支持和一些其他高級XML特性等都提供了更好的支持。 這一小節其實只是教你如何讓XML解析稍微簡單一點。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 凉城县| 武鸣县| 元阳县| 咸丰县| 黄平县| 龙山县| 蕉岭县| 临颍县| 专栏| 嫩江县| 洛宁县| 竹山县| 北宁市| 承德市| 涞源县| 彰化市| 阿克陶县| 四川省| 临澧县| 金湖县| 中方县| 南充市| 家居| 昌江| 平定县| 新余市| 湘潭县| 广宁县| 平江县| 原阳县| 沾化县| 乃东县| 夹江县| 丰都县| 新丰县| 汉中市| 新乐市| 秦皇岛市| 泌阳县| 全椒县| 石狮市|