天天看點

[Python學習]使用minidom來處理XML的示例 (二)–XML的寫入

下面我來示範一下如何從無到有生成象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/>’

對于象元素這樣的結點,生成的元素結點其實是一個空元素,即不包含任何文本,如果要包含文本或其它的元素,我們需要使用appendChild() 或insertBefore()之類的方法将子結點加就到元素結點中。如将上面生成的text結點加入到caption元素結點中:

>>> item.appendChild(text)

<DOM Text node “test”>

>>> item.toxml()

‘<caption>test</caption>’

使用元素對象的setAttribute()方法可以向元素中加入屬性,如:

>>> item.setAttribute(’id’, ‘idvalue’)

>>> item.toxml()

‘<caption id=”idvalue”>test</caption>’

四、生成dom對象樹

我們有了dom對象,又知道了如何生成各種結點,包括葉子結點(不包含其它結點的結點,如文本結點)和非葉子結點(包含其它結點的結點,如元素結 點)的生成,然後就需要利用結點對象本身的appendChild()或insertBefore()方法将各個結點根據在樹中的位置連起來,串成一棵 樹。最後要串到文檔結點上,即根結點上。如一個完整的示例為:

>>> import xml.dom.minidom

>>> impl = xml.dom.minidom.getDOMImplementation()

>>> dom = impl.createDocument(None, ‘catalog’, None)

>>> root = dom.documentElement

>>> item = dom.createElement(’item’)

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

>>> item.appendChild(text)

<DOM Text node “test”>

>>> root.appendChild(item)

<DOM Element: item at 0xb9cf80>

>>> print root.toxml()

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

五、簡單生成元素結點的函數

下面是我寫的一個小函數,用于簡單的生成類似于:

<caption>test</caption>

或形如:

<item><![CDATA[test]]></item>

的元素結點

1       def makeEasyTag(dom, tagname, value, type=’text’):

2           tag = dom.createElement(tagname)

3           if value.find(’]]>’) > -1:

4               type = ‘text’

5           if type == ‘text’:

6               value = value.replace(’&’, ‘&amp;’)

7               value = value.replace(’<’, ‘&lt;’)

8               text = dom.createTextNode(value)

9           elif type == ‘cdata’:

10              text = dom.createCDATASection(value)

11          tag.appendChild(text)

12          return tag

參數說明:

  • dom為dom對象
  • tagname為要生成元素的名字,如’item’
  • value為其文本内容,可以為多行
  • type為文本結點的格式,’text’為一般Text結點,’cdata’為CDATA結點

函數處理說明:

  • 首先建立元素結點
  • 查找文本内容是否有’]]>’,如果找到,則此文本結點隻可以是Text結點
  • 如果結點類型為’text’,則對文本内容中的’<’替換為’&lt;’,’&’替換為’&amp;’,再生成文 本結點
  • 如果結點類型為’cdata’,則生成CDATA結點
  • 将生成的文本結點追加到元素結點上

是以這個小函數可以自動地處理字元轉化及避免CDATA結點中出現’]]>’串。

上面生成’item’結點的語句可以改為:

>>> item = makeEasyTag(dom, ‘item’, ‘test’)

>>> item.toxml()

‘<item>test</item>’

六、寫入到XML檔案中

dom對象樹已經生成好了,我們可以調用dom的writexml()方法來将内容寫入檔案中。writexml()方法文法格式為:

writexml(writer, indent, addindent, newl, encoding)
  • writer是檔案對象
  • indent是每個tag前填充的字元,如:’  ‘,則表示每個tag前有兩個空格
  • addindent是每個子結點的縮近字元
  • newl是每個tag後填充的字元,如:’/n’,則表示每個tag後面有一個回車
  • encoding是生成的XML資訊頭中的encoding屬性值,在輸出時minidom并不真正進行編碼的處理,如果你儲存的文本内容中有漢 字,則需要自已進行編碼轉換。

writexml方法是除了writer參數必須要有外,其餘可以省略。下面給出一個文本内容有漢字的示例:

1       >>> import xml.dom.minidom

2       >>> impl = xml.dom.minidom.getDOMImplementation()

3       >>> dom = impl.createDocument(None, ‘catalog’, None)

4       >>> root = dom.documentElement

5       >>> text = unicode(’漢字示例’, ‘cp936′)

6       >>> item = makeEasyTag(dom, ‘item’, text)

7       >>> root.appendChild(item)

8       <DOM Element: item at 0xb9ceb8>

9       >>> root.toxml()

10      u’<catalog><item>/u6c49/u5b57/u793a/u4f8b</item></catalog>’

11      >>> f=file(’d:/test.xml’, ‘w’)

12      >>> import codecs

13      >>> writer = codecs.lookup(’utf-8′)[3](f)

14      >>> dom.writexml(writer, encoding=’utf-8′)

15      >>> writer.close()

5行 因為XML處理時内部使用Unicode編碼,是以象漢字首先要轉成Unicode,如果你不做這一步minicode并不檢查,并且儲存時可能不會出 錯。但讀取時可能會出錯。

12-13行 生成UTF-8編碼的寫入流對象,這樣在儲存時會自動将Unicode轉換成UTF-8編碼。

這樣寫XML檔案就完成了。