使用minidom來處理XML的樣本(Python 學習)(轉載)__Python

來源:互聯網
上載者:User

http://www.cnblogs.com/xuxm2007/archive/2011/01/16/1936610.html


http://blog.csdn.net/ywchen2000/archive/2006/07/04/876742.aspx 

 http://blog.csdn.net/zhangj1012003_2007/archive/2010/04/23/5514807.aspx

 http://blog.csdn.net/zhangj1012003_2007/archive/2010/04/22/5514929.aspx

 http://blog.csdn.net/zhangj1012003_2007/archive/2010/04/22/5514935.aspx

 

一.XML的讀取.

在 NewEdit 中有程式碼片段的功能,程式碼片段分為片段的分類和片段的內容。在預設情況下都是用XML格式儲存的。下面我講述一下,如何使用minidom來讀取和儲存XML檔案。

下面是片段分類的一個樣本檔案--catalog.xml

<?xml version="1.0" encoding="utf-8"?>
<catalog>
    <maxid>4</maxid>
    <item id="1">
        <caption>Python</caption>
        <item id="4">
            <caption>測試</caption>
        </item>
    </item>
    <item id="2">
        <caption>Zope</caption>
    </item>
</catalog>

分類是樹狀結構,顯示出來可能為:

Python
    測試
Zope

先簡單介紹一下XML的知識,如果你已經知道了可以跳過去。

1. XML文檔的編碼

此XML文檔的編碼為utf-8,因此你看到的“測試”其實是UTF-8編碼。在XML文檔的處理中都是使用UTF-8編碼進行的,因此,如果你不寫明encoding的話,都是認為檔案是UTF-8編碼的。在Python中,好象只支援幾種編碼,象我們常用的GB2312碼就不支援,因此建議大家在處理XML時使用UTF-8編碼。

2. XML文檔的結構

XML文檔有XML頭資訊和XML資訊體。頭資訊如:

<?xml version="1.0" encoding="utf-8"?>

它表明了此XML文檔所用的版本,編碼方式。有些複雜的還有一些文件類型的定義(DOCTYPE),用於定義此XML文檔所用的DTD或Schema和一些實體的定義。這裡並沒有用到,而且我也不是專家,就不再細說了。

XML資訊體是由樹狀元素組成。每個XML文檔都有一個文件項目,也就是樹的根項目,所有其它的元素和內容都包含在根項目中。

3. DOM

DOM是Document Object Model的簡稱,它是以對象樹來表示一個XML文檔的方法,使用它的好處就是你可以非常靈活的在對象中進行遍曆。

4. 元素和結點

元素就是標記,它是成對出現的。XML文檔就是由元素組成的,但元素與元素之間可以有文本,元素的內容也是文本。在minidom中有許多的結點,元素也屬於結點的一種,它不是葉子結點,即它存在子結點;還存在一些葉子結點,如文本結點,它下面不再有子結點。

象catalog.xml中,文件項目是catalog,它下面有兩種元素:maxid和item。maxid用來表示當前最大的item的id值。每一個item都有一個id屬性,id屬性是唯一的,在 NewEdit 中用來產生每個分類所對應的程式碼片段的XML文檔名,因此不能重複,而且它是一個遞增的值。item元素有一個caption子項目,用來表示此分類項的名稱,它還可以包含item元素。這樣,就定義了一個樹狀XML結構,下面讓我們看一看如果把它們讀出來。


一、得到dom對象

>>> import xml.dom.minidom
>>> dom = xml.dom.minidom.parse('d:/catalog.xml')

這樣我們得到了一個dom對象,它的第一個元素應該是catalog。

二、得到文件項目對象

>>> root = dom.documentElement

這樣我們得到了根項目(catalog)。

三、結點屬性

每一個結點都有它的nodeName,nodeValue,nodeType屬性。nodeName為結點名字。

>>> root.nodeName
u'catalog'

nodeValue是結點的值,只對文本結點有效。nodeType是結點的類型,現在有以下幾種:

'ATTRIBUTE_NODE'
'CDATA_SECTION_NODE'
'COMMENT_NODE'
'DOCUMENT_FRAGMENT_NODE'
'DOCUMENT_NODE'
'DOCUMENT_TYPE_NODE'
'ELEMENT_NODE'
'ENTITY_NODE'
'ENTITY_REFERENCE_NODE'
'NOTATION_NODE'
'PROCESSING_INSTRUCTION_NODE'
'TEXT_NODE'

這些結點通過名字很好理解。catalog是ELEMENT_NODE類型。

>>> root.nodeType
1
>>> root.ELEMENT_NODE
1

四、子項目、子結點的訪問

訪問子項目、子結點的方法很多,對於知道元素名字的子項目,可以使用getElementsByTagName方法,如讀取maxid子項目:

>>> root.getElementsByTagName('maxid')
[<DOM Element: maxid at 0xb6d0a8>]

這樣返回一個列表,由於我們的例子中maxid只有一項,因此列表也只有一項。

如果想得到某個元素下的所有子結點(包括元素),可以使用childNodes屬性:

>>> root.childNodes
[<DOM Text node "\n    ">, <DOM Element: maxid at 0xb6d0a8>, <DOM Text node "\n    ">, <DOM Element: item at 0xb6d918>, <DOM Text node "\n    ">, <DOM Element: item at 0xb6de40>, <DOM Text node "\n    ">, <DOM Element: item at 0xb6dfa8>, <DOM Text node "\n">]

可以看出所有兩個標記間的內容都被視為文本結點。象每行後面的斷行符號,都被看到文本結點。從上面的結果我們可以看出每個結點的類型,本例中有文本結點和元素結點;結點的名字(元素結點);結點的值(文本結點)。每個結點都是一個對象,不同的結點對象有不同的屬性和方法,更詳細的要參見文檔。由於本例比較簡單,只涉及文本結點和元素結點。

getElementsByTagName可以搜尋當前元素的所有子項目,包括所有層次的子項目。childNodes只儲存了當前元素的第一層子結點。

這樣我們可以遍曆childNodes來訪問每一個結點,判斷它的nodeType來得到不同的內容。如,列印出所有元素的名字:

>>> for node in root.childNodes:
    if node.nodeType == node.ELEMENT_NODE:
        print node.nodeName
        
maxid
item
item

對於文本結點,想得到它的常值內容可以使用: .data屬性。

對於簡單的元素,如:<caption>Python</caption>,我們可以編寫這樣一個函數來得到它的內容(這裡為Python)。

def getTagText(root, tag):
    node = root.getElementsByTagName(tag)[0]
    rc = ""
    for node in node.childNodes:
        if node.nodeType in ( node.TEXT_NODE, node.CDATA_SECTION_NODE):
            rc = rc + node.data
    return rc

這個函數只處理找到的第一個符合的子項目。它會將符合的第一個子項目中的所有文本結點拼在一起。當nodeType為文本類結點時,node.data為文本的內容。如果我們考查一下元素caption,我們可能看到:

[<DOM Text node "Python">]

說明caption元素只有一個文本結點。

如果一個元素有屬性,那麼可以使用getAttribute方法,如:

>>> itemlist = root.getElementsByTagName('item')
>>> item = itemlist[0]
>>> item.getAttribute('id')
u'1'

這樣就得到了第一個item元素的屬性值。

下面讓我們簡單地小結一下如何使用minidom來讀取XML中的資訊

1. 匯入xml.dom.minidom模組,產生dom對象
2. 得到文檔對象(根對象)
3. 通過getElementsByTagName()方法和childNodes屬性(還有其它一些方法和屬性)找到要處理的元素
4. 取得元素下文本結點的內容
二.寫入.

下面我來示範一下如何從無到有產生象catalog.xml一樣的XML檔案。

一、產生dom對象

>>> import xml.dom.minidom
>>> impl = xml.dom.minidom.getDOMImplementation()
>>> dom = impl.createDocument(None, 'catalog', None)

這樣就產生了一個空的dom對象。其中catalog為文件項目名,即根項目名。

二、顯示產生的XML內容

每一個dom結點對象(包括dom對象本身)都有輸出XML內容的方法,如:toxml(), toprettyxml()

toxml()輸出緊湊格式的XML文本,如:

<catalog><item>test</item><item>test</item></catalog>

toprettyxml()輸出美化後的XML文本,如:

<catalog>
    <item>
        test
    </item>
    <item>
        test
    </item>
</catalog>

可以看出,它是將每個結點後面都加入了斷行符號符,並且自動處理縮近。但對於每一個元素,如果元素只有常值內容,則我希望元素的tag與文本是在一起的,如:

<item>test</item>

而不想是分開的格式,但minidom本身是不支援這樣的處理。關於如何?形如:

<catalog>
    <item>test</item>
    <item>test</item>
</catalog>

這樣的XML格式,後面我們再說。

三、產生各種結點對象

dom對象擁有各種產生結點的方法,下面列出文本結點,CDATA結點和元素結點的產生過程。

1. 文本結點的產生

>>> text=dom.createTextNode('test')
test

要注意的是,在產生結點時,minidom並不對文本字元進行檢查,象文本中如果出現了'<','&'之類的字元,應該轉換為相應的實體符號'&lt;','&amp;'才可以,這裡沒有做這個處理。

2. CDATA結點的產生

>>> data = dom.createCDATASection('aaaaaa\nbbbbbb')
>>> data.toxml()
'<![CDATA[aaaaaa\nbbbbbb]]>'

CDATA是用於包括大塊文本,同時可以不用轉換'<','&'字元的標記,它是用<![CDATA[文本]]>來包括的。但文本中不可以有"]]>"這樣的串存在。產生結點時minidom不作這些檢查,只有當你輸出時才有可能發現有錯。

3. 元素結點的產生

>>> item = dom.createElement('caption')
>>> item.toxml()
'<caption/>'

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.