python进阶(十七)xml(下)
1、XML簡(jiǎn)介
xml用到的地方:tomcat配置文件
1) xml 指可擴(kuò)展標(biāo)記語言(Extensible Markup Language)
2) xml 被設(shè)計(jì)用于結(jié)構(gòu)化、存儲(chǔ)和傳輸數(shù)據(jù)
3) xml 是一種標(biāo)記語言,很類似于HTML
4) xml 沒有像HTML那樣具有預(yù)定義標(biāo)簽,需要程序員自定義標(biāo)簽
5) xml 被設(shè)計(jì)為具有自我描述性,并且是W3C的標(biāo)準(zhǔn)。
?
?2、xml和html的區(qū)別:
html是xml的一種特例。html里面的標(biāo)簽全都是已經(jīng)預(yù)定義好的,都是有含義的。
xml的數(shù)據(jù)存儲(chǔ)和顯示是分開的,存儲(chǔ)一個(gè)文件,顯示一個(gè)文件,xml不需要標(biāo)簽,可以自定義。
xml:
<bookstore>
<book>
<name>技術(shù)指南</name>
</book>
</bookstore>
如果將以上內(nèi)容放進(jìn)瀏覽器中,瀏覽器中可以看到,但是不能像html顯示各種樣式。
如果將以上xml也能作為網(wǎng)頁顯示,如何實(shí)現(xiàn)?
?
3、html5實(shí)例:
網(wǎng)址鏈接:
http://www.w3school.com.cn/tiy/t.asp?f=html5_video_all
代碼:
<!DOCTYPE HTML>
<html>
<body>
?
<video width="320" height="240" controls="controls">
? <source src="/i/movie.ogg" type="video/ogg">
? <source src="/i/movie.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
?
</body>
</html>
?
html5比html4的區(qū)別就是多了很多標(biāo)簽
<h1>我的第一個(gè)標(biāo)題</h1>
<p>我的死一個(gè)段落。</p>
<div>塊
<title>標(biāo)題
?
?
4、AJAX
AJAX = Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。
AJAX 不是新的編程語言,而是一種使用現(xiàn)有標(biāo)準(zhǔn)的新方法。
AJAX 是與服務(wù)器交換數(shù)據(jù)并更新部分網(wǎng)頁的藝術(shù),在不重新加載整個(gè)頁面的情況下。
實(shí)際用處:比如,注冊(cè)頁面,用戶名還未提交,就提示該用戶名已被使用
該技術(shù)的好處:不用刷新頁面,重新加載頁面要3s,而AJAX需要幾十-幾百毫秒。
異步傳輸:5個(gè)步驟,誰先執(zhí)行都可以,沒有先后順序,可以并發(fā)
同步傳輸:按照順序傳輸,1,2,3,4,5
?
5、CMS(content management system,新聞發(fā)布系統(tǒng))
?
6、Apache和tomcat的區(qū)別:
Apache只能做靜態(tài)網(wǎng)頁的顯示。
tomcat既能動(dòng)態(tài)也能靜態(tài)
靜態(tài)網(wǎng)頁:網(wǎng)頁一旦生成好,網(wǎng)頁是不變的。訪問的內(nèi)容是一樣的。
動(dòng)態(tài)網(wǎng)頁:是根據(jù)你的請(qǐng)求數(shù)據(jù)和服務(wù)器的處理規(guī)則實(shí)時(shí)生成的網(wǎng)頁。
?
7、XML文檔(樹結(jié)構(gòu))
XML文檔形成了一種樹結(jié)構(gòu),它從”根部開始”,然后擴(kuò)展到“樹枝”。
XML文檔必須包含根元素,該元素是所有其他元素的父元素,文芳中的所有元素形成了一棵文檔樹,這棵樹從根開始,并擴(kuò)展到樹的最頂端,并且所有的元素都可以有子元素。
<root>
<child>
<subchild>...</subchild>
</child>
</root>
父元素?fù)碛凶釉?#xff0c;相同層級(jí)上的子元素成為同胞(兄弟或姐妹)。XML中所有子元素都可以有文本內(nèi)容和屬性,類似于HTML.
?
?8、XML基礎(chǔ)知識(shí)介紹
1) XML元素
????? XML元素是指開始標(biāo)簽到結(jié)束標(biāo)簽的部分(均包括開始結(jié)束)。
????? 一個(gè)元素可以包含:
????? 1. 其他元素
????? 2. 文本
????? 3. 屬性
????? 4. 或混合以上所有
<!--? Edited with XML Spy v2007 (http://www.altova.com)? --> #xml注釋
<catalog>????????????????????????????????????????????????????????????? #根元素
<cd>??????????????????????????????????????????????????????????????????? #子標(biāo)簽
<title>Empire Burlesque</title>? # Empire Burlesque文本節(jié)點(diǎn),和空格也是文本節(jié)點(diǎn),<>內(nèi)的內(nèi)容是element 節(jié)點(diǎn)
<artist>Bob Dylan</artist>??????? #<title>為標(biāo)簽
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>...</cd>
</catalog>
?
<cd class = "classic">??? #class = "classic"為屬性,做輔助說明的
<a href = "http://www.souhu.com">souhu</a>
# href = http://www.souhu.com標(biāo)簽里面的內(nèi)容,以=顯示的叫做屬性
#點(diǎn)擊souhu這個(gè)藍(lán)字,會(huì)跳轉(zhuǎn)到http://www.souhu.com這個(gè)網(wǎng)頁中
?????
2) XML語法規(guī)則
????? 1. 所有的XML元素都必須有一個(gè)開始標(biāo)簽和結(jié)束標(biāo)簽,省略結(jié)束標(biāo)簽是非法的。如:
???????? <root>content</root>
????? 2. html可以少一個(gè)標(biāo)簽,因?yàn)闉g覽器會(huì)自動(dòng)糾錯(cuò),瀏覽器怎么解析html都不會(huì)崩潰。如果少一個(gè)標(biāo)簽,也可以解析,不過解析的內(nèi)容可能和預(yù)期有差異。
???????? <title>光榮之路
????? 3. XML標(biāo)簽對(duì)大小寫敏感;比如:下面時(shí)兩個(gè)不同的標(biāo)簽
???????? <Note>this is a test1<Note>
???????? <note>this is a test2<note>
????? 4. XML文檔必須有根元素。如:
<note>
??? <b>this is a test2</b>
??? <name>joy</name>
</note>
????? 5. XML必須正確嵌套,父元素必須完全包住子元素。如:
<note><b>this is a test2</b><name>joy</name></note>
????? 6. XML屬性值必須加引號(hào),元素的屬性值都是一個(gè)鍵值對(duì)形式。如:
<book catgory = “Python”></book>
??????? 注意:
???????????? book元素中的屬性category的值是Python必須用引號(hào)引起來,使用單引號(hào)和雙引號(hào)都可以,但是如果屬性值本身包含雙引號(hào),外層必須使用單引號(hào);但如果包含了單引號(hào),外層必須使用雙引號(hào)。
?
9、XML命名規(guī)則
XML元素必須遵循以下命名規(guī)則:
1)名稱可以包含字母、數(shù)字以及其他字符
2)名稱不能以數(shù)字或標(biāo)點(diǎn)符號(hào)開頭
3)名稱不能以字母xml或XML開始
4)名稱不能包含空格
5)可以使用任何名稱,沒有保留字
6)名稱應(yīng)該具有描述性,簡(jiǎn)短和簡(jiǎn)單,可以同時(shí)使用下劃線。
7)避免-、.、:等字符
8)XML的注釋格式為:<! -- 注釋內(nèi)容 -->??????? #和html的注釋一樣。
#注釋的內(nèi)容不會(huì)作為瀏覽器顯示的內(nèi)容,也不會(huì)作為XML解析的內(nèi)容
?
10、CDATA
CDATA(Unparsed Character Data)指的是不應(yīng)由XML解析器進(jìn)行解析的文本數(shù)據(jù)。
XML解析器會(huì)將“<”(新元素的開始)和”&”(字符實(shí)體的開始)解析成具有特殊漢含義的字符。當(dāng)代碼中含有大量的“<”和”&”符號(hào),可以將腳本定義為CDATA來避免這個(gè)問題,因?yàn)閄ML文檔中的所有文本均會(huì)被解析器解析,只有CDATA部分中的所有的內(nèi)容會(huì)被XML解析器忽略。
<![CDATA[“我們自己的代碼”]]>
注意:CDATA部分不能包含字符串”]]>”,并且”]]>”之間不能有空格或折行等字符,如果包含了,會(huì)以為是CDATA的結(jié)束。也不允許嵌套CDATA部分。
<script>
<![CDATA[
function test(x,y)
??? { if (x<0 &&y<0) then
??????? {
??????????? return 0;
??????? }
??????? else
??????? {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
??????????? return 1:
}
]]>
</script>
?
11、Python解析XML三種方法
1)SAX(simple API for XML)
Python標(biāo)準(zhǔn)庫中包含SAX解析器,SAX是用的是事件驅(qū)動(dòng)模型,通過在解析XML過程中觸發(fā)一個(gè)個(gè)的事件并調(diào)用用戶定義的回調(diào)函數(shù)來處理XML文件。
解析的基本過程:
讀到一個(gè)XML開始標(biāo)簽,就會(huì)開始一個(gè)事件,然后事件就會(huì)調(diào)用一系列的函數(shù)去處理一些事情,當(dāng)讀到一個(gè)結(jié)束標(biāo)簽時(shí),就會(huì)觸發(fā)另一個(gè)事件。所以,我們寫XML文檔如果有格式錯(cuò)誤的話解析就會(huì)出錯(cuò)。
這是一種流式處理,一邊讀一邊解析,占用內(nèi)存少,但速度慢。
2) DOM(Document Object Model)
DOM它是以對(duì)象樹來表示一個(gè)XML文檔的方法,使用它的好處就是你可以非常靈活的在對(duì)象中進(jìn)行遍歷。
將XML數(shù)據(jù)在內(nèi)存中解析成一個(gè)樹,通過對(duì)樹的操作來操作XML.
由于DOM是將XML讀取到內(nèi)存,然后解析成一個(gè)樹,如果要處理的XML文件比較大的話,就會(huì)很耗內(nèi)存,所以DOM一般偏向于處理一些小的XML,(如配置文件)比較快
占內(nèi)存,但是速度快。--建議這種,因?yàn)閤ml現(xiàn)在普遍挺小,內(nèi)存已經(jīng)不是瓶頸。
3) ElementTree(Object Model)
ElementTree就像一個(gè)輕量級(jí)的DOM,具有方便而友好的API.代碼的可用性好、速度快,消耗內(nèi)存少。可以認(rèn)為是對(duì)DOM的改進(jìn)。
支持XPATH,定位元素的一種方式。自動(dòng)化定位元素的一種方式。
?
12、Xml.dom解析xml
xml.dom解析xml的思路:
一個(gè)DOM的解析器在解析一個(gè)XML文檔時(shí),一次性讀取整個(gè)文檔,把文檔中所有元素保存在內(nèi)存中的一個(gè)樹結(jié)構(gòu)里,之后利用DOM提供的不同函數(shù)來讀取該文檔的內(nèi)容和結(jié)構(gòu),也可以把修改過的內(nèi)容寫入XML文件。
<?xml version="1.0" encoding="utf-8" ?>???????? ?#xml文件頭
<!--this is a test about xml.-->?????????????????? ?#注釋
<booklist type="science and engineering">??????? #根節(jié)點(diǎn)
<book category="math">
<title>learning math</title>
<author>張三</author>
<pageNumber>561</pageNumber>
</book>
<book category="Python">
<title>learning Python</title>
<author>李四</author>
<pageNumber>600</pageNumber>
</book>
</booklist>
#以上是book.xml文檔的內(nèi)容
?
13、xml.dom解析xml常用API
1) minidom.parse(parser=None,bufsize=None)
from xml.dom.minidom import parse?? #從xml.dom.minidom模塊引入解析器parse
DOMTree = parse(r"e:\book.xml")???? #minidom解析器打開xml文檔并將其解析為內(nèi)存中的一棵樹
print(type(DOMTree))
#<class 'xml.dom.minidom.Document'> #xml的document對(duì)象
#minidom.parse(parser=None,bufsize=None)
#該函數(shù)的作用是使用parse解析器打開XML文檔,并將其解析為DOM文檔,也就是內(nèi)存中的一棵樹,并得到這個(gè)DOM對(duì)象。
?
2) doc.documentElement:獲取xml文檔對(duì)象,就是拿到DOM樹的根
>>> from xml.dom.minidom import parse
>>> DOMTree = parse(r"e:\book.xml")
>>> booklist = DOMTree.documentElement
>>> print(booklist)
<DOM Element: booklist at 0x28471659b90>?? #booklist是根節(jié)點(diǎn)
?
3) doc.toxml:獲取xml文本內(nèi)容
>>> print(DOMTree.toxml)
<bound method Node.toxml of <xml.dom.minidom.Document object at 0x000002847165AA08>>
>>> print(DOMTree.toxml())???????????? #將xml中的內(nèi)容除了根節(jié)點(diǎn)的內(nèi)容都打印一下
<?xml version="1.0" ?><!--this is a test about xml.--><booklist type="science and engineering">
<book category="math">
<title>learning math</title>
<author>張三</author>
<pageNumber>561</pageNumber>
</book>
<book category="Python">
<title>learning Python</title>
<author>李四</author>
<pageNumber>600</pageNumber>
</book>
</booklist>
>>>?
?
4) has Attribute:判斷是否包含屬性
>>> from xml.dom.minidom import parse??
>>> DOMTree = parse(r"e:\book.xml")? ??#minidom解析器打開xml文檔并將其解析為內(nèi)存中的一棵樹
>>> booklist = DOMTree.documentElement #獲取xml文檔對(duì)象,就是拿到樹的根
>>> print(u"DOM樹的根對(duì)象:", booklist)
#DOM樹的根對(duì)象: <DOM Element: booklist at 0x28471659af8>
>>> if booklist.hasAttribute("type"):? ????#判斷根節(jié)點(diǎn)booklist是否有type屬性
...???? print(u"booklist元素存在type屬性")
... else :
...???? print(u"booklist元素不存在type屬性")
...
booklist元素存在type屬性
>>>?
?
5) node.getAttrbute:獲取節(jié)點(diǎn)node的某個(gè)屬性值
>>> from xml.dom.minidom import parse??
>>> DOMTree = parse(r"e:\book.xml")? ??#minidom解析器打開xml文檔并將其解析為內(nèi)存中的一棵樹
>>> booklist = DOMTree.documentElement #獲取xml文檔對(duì)象,就是拿到樹的根
>>> print(u"DOM樹的根對(duì)象:", booklist)
#DOM樹的根對(duì)象: <DOM Element: booklist at 0x284716595a0>
>>> if booklist.hasAttribute("type"):? ????#判斷根節(jié)點(diǎn)booklist是否有type屬性
...???? print(u"Root element is",booklist.getAttribute("type"))
...
Root element is science and engineering
?
6) node.getElementsByTagName(name):獲取節(jié)點(diǎn)元素
獲取XML文檔中某個(gè)父節(jié)點(diǎn)下具有相同節(jié)點(diǎn)名的節(jié)點(diǎn)對(duì)象集合,是一個(gè)list對(duì)象。
>>> from xml.dom.minidom import parse??
>>> DOMTree = parse(r"e:\book.xml")? ??#minidom解析器打開xml文檔并將其解析為內(nèi)存中的一棵樹
>>> booklist = DOMTree.documentElement #獲取xml文檔對(duì)象,就是拿到樹的根
>>> print(u"DOM樹的根對(duì)象:", booklist)
#DOM樹的根對(duì)象: <DOM Element: booklist at 0x28471513c28>
>>> books = booklist.getElementsByTagName("book") ?#獲取根節(jié)點(diǎn)下標(biāo)簽是book的
>>> print(type(books))???????????????????????????? ???#節(jié)點(diǎn)對(duì)象,該返回值是個(gè)list
<class 'xml.dom.minicompat.NodeList'>
>>> print(books)
[<DOM Element: book at 0x28471513a60>, <DOM Element: book at 0x28471513638>]
>>> print(books[0])
<DOM Element: book at 0x28471513a60>
#上面解析xml的程序中,getElementsByTagName()函數(shù)返回的是同一父節(jié)點(diǎn)下所有同級(jí)(即兄弟節(jié)點(diǎn))節(jié)點(diǎn)中相同標(biāo)簽的集合,這是一個(gè)list對(duì)象,所以可以使用list序列所有操作。這個(gè)時(shí)候,我們可以通過索引去拿相應(yīng)的節(jié)點(diǎn),也可以使用節(jié)點(diǎn)名稱去拿相應(yīng)的節(jié)點(diǎn),推薦第二種方法,準(zhǔn)確。也可以循環(huán)遍歷整個(gè)返回的list。
注意:
就算某個(gè)父節(jié)點(diǎn)下沒有同名的節(jié)點(diǎn),該方法返回的仍是一個(gè)list,只是此時(shí)的list為空。
?
7) node.childNodes:返回節(jié)點(diǎn)node下所有子節(jié)點(diǎn)組成的list
>>> from xml.dom.minidom import parse??
>>> DOMTree = parse(r"e:\book.xml")? ??#minidom解析器打開xml文檔并將其解析為內(nèi)存中的一棵樹
>>> booklist = DOMTree.documentElement #獲取xml文檔對(duì)象,就是拿到樹的根
>>> print(u"DOM樹的根對(duì)象:", booklist)
#DOM樹的根對(duì)象: <DOM Element: booklist at 0x284716595a0>
>>> books = booklist.getElementsByTagName("book")#返回父節(jié)點(diǎn)下標(biāo)簽為book的節(jié)點(diǎn)
>>> print(books[0].childNodes)????????? ?#返回第一個(gè)book節(jié)點(diǎn)下的所有的子節(jié)點(diǎn)
[<DOM Text node "'\n'">, <DOM Element: title at 0x28471513898>, <DOM Text node "'\n'">, <DOM Element: author at 0x284715139c8>, <DOM Text node "'\n'">, <DOM Element: pageNumber at 0x28471513930>, <DOM Text node "'\n'">]
#<DOM Text node "'\n'">是換行,如果不想取換行,拿到所有的子節(jié)點(diǎn),不要文本節(jié)點(diǎn),如何做?
>>> print((books[0].childNodes)[1::2])??? ???#使用切片實(shí)現(xiàn)
[<DOM Element: title at 0x28471513898>, <DOM Element: author at 0x284715139c8>, <DOM Element: pageNumber at 0x28471513930>]
?
8) 獲取節(jié)點(diǎn)文本值重要!!
1.
from xml.dom.minidom import parse? #從xml.dom.minidom模塊引入解析器parse
DOMTree = parse(r"e:\book.xml")??? #minidom解析器打開xml文檔并將其解析為內(nèi)存中的一棵樹
print(type(DOMTree))
<class 'xml.dom.minidom.Document'>
booklist = DOMTree.documentElement
print(booklist)
<DOM Element: booklist at 0x23b6dba2b90>
print("*"*30)
******************************
books = booklist.getElementsByTagName("book")
d={}
for i in range(1,6,2):
??? tag_name = books[1].childNodes[i].tagName ?????????#讀取標(biāo)簽名字
??? d[tag_name]=books[1].childNodes[i].childNodes[0].data ?#讀取標(biāo)簽值
print(d)????????????? ?#標(biāo)簽值(文本節(jié)點(diǎn))對(duì)于標(biāo)簽來說是一個(gè)子節(jié)點(diǎn)
{'title': 'learning Python', 'author': '李四', 'pageNumber': '600'}
for k,v in d.items():
??? print(k,v)
title learning Python
author 李四
pageNumber 600
.data讀取文本節(jié)點(diǎn)的值,.data是文本對(duì)象的屬性,必須是文本對(duì)象才可用.data
.tagname讀取標(biāo)簽值
element節(jié)點(diǎn)在<>中,文本節(jié)點(diǎn)是看不見的換行和文字內(nèi)容
?
2.
import xml.dom.minidom
from xml.dom.minidom import parse??
DOMTree = xml.dom.minidom.parse(r"e:\book.xml")? #minidom解析器打開xml文檔并將其解析為內(nèi)存中的一棵樹
booklist = DOMTree.documentElement #獲取xml文檔對(duì)象,就是拿到樹的根
if booklist.hasAttribute("type") :? #判斷根節(jié)點(diǎn)booklist是否有type屬性,有則獲取并打印屬性的值
print(u"Root element is", booklist.getAttribute("type"))??
books = booklist.getElementsByTagName("book") #獲取booklist對(duì)象中所有book節(jié)點(diǎn)的list集合
print(u"book節(jié)點(diǎn)的個(gè)數(shù):", books.length)
for book in books :
??? print("*******************book*******************")
??? if book.hasAttribute("category") :
??????? print(u"category is", book.getAttribute("category"))
#根據(jù)節(jié)點(diǎn)名title拿到這個(gè)book節(jié)點(diǎn)下所有的title節(jié)點(diǎn)的集合list。
#[0]表示第一個(gè)title標(biāo)簽,因?yàn)橐粋€(gè)<book>...</book>之間可能會(huì)
#定義多個(gè)title標(biāo)簽
??? title = book.getElementsByTagName('title')[0]
??? print("Title is", title.childNodes[0].data)
??? author = book.getElementsByTagName('author')[0]
??? print("author is", author.childNodes[0].data)
??? pageNumber = book.getElementsByTagName('pageNumber')[0]
??? print("pageNumber is", pageNumber.childNodes[0].data)
運(yùn)行結(jié)果:
E:\>python a.py
Root element is science and engineering
book節(jié)點(diǎn)的個(gè)數(shù): 2
*******************book*******************
category is math
Title is learning math
author is 張三
pageNumber is 561
*******************book*******************
category is Python
Title is learning Python
author is 李四
pageNumber is 600
?
9) node.haschildNodes():判斷是否有子節(jié)點(diǎn)
判斷節(jié)點(diǎn)node下是否有葉子節(jié)點(diǎn),如果有返回True,否則返回False。但是需要注意的是,每個(gè)節(jié)點(diǎn)都默認(rèn)有一個(gè)文本葉子節(jié)點(diǎn),所以標(biāo)簽后面有值,就返回True,只有當(dāng)標(biāo)簽后沒值時(shí)并且也沒有葉子節(jié)點(diǎn)時(shí)才會(huì)返回False.
import xml.dom.minidom
from xml.dom.minidom import parse
#minidom解析器打開xml文檔并將其解析為內(nèi)存中的一棵樹
DOMTree = xml.dom.minidom.parse(r"e:\book.xml")
#獲取xml文檔對(duì)象,就是拿到樹的根
booklist = DOMTree.documentElement
#獲取booklist對(duì)象中所有book節(jié)點(diǎn)的list集合
books = booklist.getElementsByTagName("book")
print(u"book節(jié)點(diǎn)的個(gè)數(shù):", books.length)
book節(jié)點(diǎn)的個(gè)數(shù): 2
print(books[0])
<DOM Element: book at 0x21a3acd06d0>
if books[0].hasChildNodes():
??? print(u"存在葉子節(jié)點(diǎn)\n", books[0].childNodes)
else :
??? print(u"不存在葉子節(jié)點(diǎn)")
存在葉子節(jié)點(diǎn)
?[<DOM Text node "'\n'">, <DOM Element: title at 0x21a3acd0768>, <DOM Text node "'\n'">, <DOM Element: author at 0x21a3acd0800>, <DOM Text node "'\n'">, <DOM Element: pageNumber at 0x21a3acd0898>, <DOM Text node "'\n'">]
?
?
14、xml.dom創(chuàng)建xml文件
創(chuàng)建xml文件的步驟如下:
1. 創(chuàng)建xml空文檔(在內(nèi)存中創(chuàng)建,未在本地生成一個(gè)文檔)
2. 產(chǎn)生根對(duì)象
3. 往根對(duì)象里加數(shù)據(jù)
4. 把xml內(nèi)存對(duì)象寫到文件
?
1) minidom.Document():創(chuàng)建xml空白文檔
該方法用于創(chuàng)建一個(gè)空白的xml文檔,并返回這個(gè)doc對(duì)象
每個(gè)xml文檔都是一個(gè)Document對(duì)象,代表著內(nèi)存中的DOM樹。
>>> import xml.dom.minidom
>>> doc = xml.dom.minidom.Document()?? #創(chuàng)建空白xml文檔
>>> print(doc)
<xml.dom.minidom.Document object at 0x00000172BBBDCAC8>
?
2) doc.createElement(tagName):創(chuàng)建xml文檔根節(jié)點(diǎn)
生成xml文檔節(jié)點(diǎn)。參數(shù)表示要生成節(jié)點(diǎn)的名稱
>>> import xml.dom.minidom
>>> doc = xml.dom.minidom.Document()
>>> print(doc)
<xml.dom.minidom.Document object at 0x00000172BBBDCAC8>
>>> root = doc.createElement("Manegers")
>>> print(u"添加的xml的標(biāo)簽為:",root.tagName)
添加的xml的標(biāo)簽為: Manegers???? #同樣未寫到文件中,保存在內(nèi)存中。
?
?? 3) node.setAttribute(attname,value):添加節(jié)點(diǎn)屬性值對(duì)
參數(shù)說明:
attname:屬性的名稱
value: 屬性的值
>>> root.setAttribute("company","xx科技")
>>> value = root.getAttribute("company")
>>> print("root元素的company的屬性值是:",value)
root元素的company的屬性值是: xx科技
?
?? 4) doc.createTextNode(data):添加文本節(jié)點(diǎn)
>>> ceo = doc.createElement("CEO")?? #CEO節(jié)點(diǎn)并沒有掛在根節(jié)點(diǎn)下
>>> ceo.appendChild(doc.createTextNode("吳總")) #文本節(jié)點(diǎn)”吳總”必須依附于element節(jié)點(diǎn)ceo下,等價(jià)于<CEO>吳總</CEO>
<DOM Text node "'吳總'">
>>> print(ceo.tagName)
CEO
?
5) doc/parentNode.appendChild(node):添加子節(jié)點(diǎn)
將節(jié)點(diǎn)node添加到文檔對(duì)象doc作為文檔樹的根節(jié)點(diǎn)或者添加到父節(jié)點(diǎn)parentNode下作為其子節(jié)點(diǎn)。
import xml.dom.minidom
doc = xml.dom.minidom.Document()?? #在內(nèi)存中創(chuàng)建一個(gè)空的文檔
root = doc.createElement('companys') ?#創(chuàng)建一個(gè)根節(jié)點(diǎn)company對(duì)象
root.setAttribute('name', u'公司信息')? ?# 給根節(jié)點(diǎn)root添加屬性
doc.appendChild(root)?????????????? #將根節(jié)點(diǎn)添加到文檔對(duì)象中
company = doc.createElement('gloryroad') # 給根節(jié)點(diǎn)添加一個(gè)葉子節(jié)點(diǎn)
name = doc.createElement("Name") ??# 葉子節(jié)點(diǎn)下再嵌套葉子節(jié)點(diǎn)
name.appendChild(doc.createTextNode(u"光榮之路教育科技公司"))#給節(jié)點(diǎn)添加文本節(jié)點(diǎn)
ceo = doc.createElement('CEO')
ceo.appendChild(doc.createTextNode(u'吳總'))
company.appendChild(name) ?#將各葉子節(jié)點(diǎn)添加到父節(jié)點(diǎn)company中
company.appendChild(ceo)
root.appendChild(company) ??#然后將company添加到跟節(jié)點(diǎn)companys中
print(doc.toxml())
<?xml version="1.0" ?>
<companys name="公司信息">
<gloryroad>
<Name>光榮之路教育科技公司</Name>
<CEO>吳總</CEO>
</gloryroad>
</companys>
?
6) doc.writexml():生成xml文檔
函數(shù)原型:
writexml(writer,indent = “”,addindent = “”,newl = “”,encoding=None)
該方法用于將內(nèi)存中xml文檔樹寫入文件中,并保存在本地磁盤
參數(shù)說明:
writer:要寫的目標(biāo)文件的文件對(duì)象
indent:指明根節(jié)點(diǎn)縮進(jìn)方式
addindent:指明子節(jié)點(diǎn)縮進(jìn)方式
newl:針對(duì)新行,指明換行方式
encoding:指明所寫xml文檔的編碼
?
import xml.dom.minidom
doc = xml.dom.minidom.Document()?? #在內(nèi)存中創(chuàng)建一個(gè)空的文檔
root = doc.createElement('companys') ?#創(chuàng)建一個(gè)根節(jié)點(diǎn)company對(duì)象
root.setAttribute('name', u'公司信息')? ?# 給根節(jié)點(diǎn)root添加屬性
doc.appendChild(root)?????????????? #將根節(jié)點(diǎn)添加到文檔對(duì)象中
company = doc.createElement('gloryroad') # 給根節(jié)點(diǎn)添加一個(gè)葉子節(jié)點(diǎn)
name = doc.createElement("Name") ??# 葉子節(jié)點(diǎn)下再嵌套葉子節(jié)點(diǎn)
name.appendChild(doc.createTextNode(u"光榮之路教育科技公司"))#給節(jié)點(diǎn)添加文本節(jié)點(diǎn)
ceo = doc.createElement('CEO')
ceo.appendChild(doc.createTextNode(u'吳總'))
company.appendChild(name) ?#將各葉子節(jié)點(diǎn)添加到父節(jié)點(diǎn)company中
company.appendChild(ceo)
root.appendChild(company) ??#然后將company添加到根節(jié)點(diǎn)companys中
fp = open(“e:\\company.xml”,”w”,encoding = “utf-8”)
doc.writexml(fp,indent=‘ ’,addindent=”\t”,newl=”\n”,encoding =”utf-8”)
fp.close()? #indent=” ”是對(duì)根節(jié)點(diǎn)生效的。可以看見下面的結(jié)果根節(jié)點(diǎn)前有個(gè)” ”
在e:\\company.xml的文件顯示的內(nèi)容是:
<?xml version="1.0" encoding="utf-8"?>
?<companys name="公司信息">
??? <gloryroad>
???????????? <Name>光榮之路教育科技公司</Name>
???????????? <CEO>吳總</CEO>
? ??? </gloryroad>
?</companys>
?
?
15、xml.dom創(chuàng)建xml的完整實(shí)例
import xml.dom.minidom
#在內(nèi)存中創(chuàng)建一個(gè)空的文檔
doc = xml.dom.minidom.Document()
?
#創(chuàng)建一個(gè)根節(jié)點(diǎn)Managers對(duì)象
root = doc.createElement('Managers')
?
#設(shè)置根節(jié)點(diǎn)的屬性
root.setAttribute('company', 'xx科技')
root.setAttribute('address', '科技軟件園')
?
#將根節(jié)點(diǎn)添加到文檔對(duì)象中
doc.appendChild(root)
?
managerList = [{'name' : 'joy', 'age' : 27, 'sex' : '女'},
{'name' : 'tom', 'age' : 30, 'sex' : '男'},
{'name' : 'ruby', 'age' : 29, 'sex' : '女'} ]
?
for i in managerList :
??? nodeManager = doc.createElement('Manager')
?? ?nodeName = doc.createElement('name')
??? #給葉子節(jié)點(diǎn)name設(shè)置一個(gè)文本節(jié)點(diǎn),用于顯示文本內(nèi)容
??? nodeName.appendChild(doc.createTextNode(str(i['name'])))
??? nodeAge = doc.createElement("age")
??? nodeAge.appendChild(doc.createTextNode(str(i["age"])))
??? nodeSex = doc.createElement("sex")
??? nodeSex.appendChild(doc.createTextNode(str(i["sex"])))
??? #將各葉子節(jié)點(diǎn)添加到父節(jié)點(diǎn)Manager中,
??? #最后將Manager添加到根節(jié)點(diǎn)Managers中
??? nodeManager.appendChild(nodeName)
??? nodeManager.appendChild(nodeAge)
??? nodeManager.appendChild(nodeSex)
??? root.appendChild(nodeManager)
?
#開始寫xml文檔
fp = open('e:\\Manager.xml', 'w')
doc.writexml(fp, indent='\t', addindent='\t', newl='\n', encoding="utf-8")
fp.close()
Manager.xml文件的內(nèi)容是:
<?xml version="1.0" encoding="utf-8"?>
?????? <Managers address="科技軟件園" company="xx科技">
????????????? <Manager>
???????????????????? <name>joy</name>
???????????????????? <age>27</age>
???????????????????? <sex>女</sex>
????????????? </Manager>
????????????? <Manager>
???????????????????? <name>tom</name>
???????????????????? <age>30</age>
???????????????????? <sex>男</sex>
????????????? </Manager>
????????????? <Manager>
???????????????????? <name>ruby</name>
???????????????????? <age>29</age>
???????????????????? <sex>女</sex>
????????????? </Manager>
?????? </Managers>
?
?
?
16. Etree
movies.xml:
<collection shelf="New Arrivals">
<movie title="Enemy Behind">
?? <type>War, Thriller</type>
?? <format>DVD</format>
?? <year>2003</year>
?? <rating>PG</rating>
?? <stars>10</stars>
?? <description>Talk about a US-Japan war</description>
</movie>
<movie title="Transformers">
?? <type>Anime, Science Fiction</type>
?? <format>DVD</format>
?? <year>1989</year>
?? <rating>R</rating>
?? <stars>8</stars>
?? <description>A schientific fiction</description>
</movie>
<movie title="Trigun">
?? <type>Anime, Action</type>
?? <format>DVD</format>
?? <episodes>4</episodes>
?? <rating>PG</rating>
?? <stars>10</stars>
?? <description>Vash the Stampede!</description>
</movie>
<movie title="Ishtar">
?? <type>Comedy</type>
?? <format>VHS</format>
?? <rating>PG</rating>
?? <stars>2</stars>
?? <description>Viewable boredom</description>
</movie>
</collection>
?
1). 遍歷xml文件:
import sys
try:
??? import xml.etree.cElementTree as ET ?#as ET作為別名,是用c語言寫的Etree的包,比不帶c的包快,但是有可能這個(gè)包沒有
except ImportError:
??? import xml.etree.ElementTree as ET? ?#如果沒有,就引入不帶c的包
tree = ET.ElementTree(file='e:\\movies.xml') #打開movies.xml文件
root=tree.getroot()?? #獲取根節(jié)點(diǎn)
#<Element 'collection' at 0x0000024FA6D96B88>
print (root.tag)???? ?#獲取根節(jié)點(diǎn)的標(biāo)簽
#collection
print (root.attrib)? ?#獲取根節(jié)點(diǎn)的屬性值,返回值是字典
#{'shelf': 'New Arrivals'}
print (root.attrib[“shelf”])? #獲取指定屬性的屬性值
#New Arrivals
for child_of_root in root:? #獲取root下一級(jí)的子節(jié)點(diǎn),并打印標(biāo)簽和屬性
??? print (child_of_root.tag)
??? print ("********", child_of_root.attrib)
?
#movie
#******** {'title': 'Enemy Behind'}
#movie
#******** {'title': 'Transformers'}
#movie
#******** {'title': 'Trigun'}
#movie
#******** {'title': 'Ishtar'}
print ("*"*50)
# **************************************************
print (root[0].tag)???? #打印一個(gè)movie
#movie
print (root[0].text) ???#第一個(gè)movie的文本節(jié)點(diǎn),“打印的內(nèi)容為一個(gè)回車”
??????????????????????? #打印內(nèi)容為一個(gè)回車
print (root[0][0].tag)? #獲取第一個(gè)movie下面的子節(jié)點(diǎn)的標(biāo)簽
#type
print (root[0][0].text) #獲取第一個(gè)movie下面的子節(jié)點(diǎn)的文本內(nèi)容
# War, Thriller
print ("*"*50)
**************************************************
for elem in tree.iter():? #遞歸遍歷所有子元素
??? print (elem.tag, elem.attrib)
#collection {'shelf': 'New Arrivals'}
#movie {'title': 'Enemy Behind'}
#type {}
#format {}
#year {}
#rating {}
#stars {}
#description {}
#movie {'title': 'Transformers'}
#type {}
#format {}
#year {}
#rating {}
#stars {}
#description {}
#movie {'title': 'Trigun'}
#type {}
#format {}
#episodes {}
#rating {}
#stars {}
#description {}
#movie {'title': 'Ishtar'}
#type {}
#format {}
#rating {}
#stars {}
#description {}
print ("*"*50)
**************************************************
for elem in tree.iterfind('movie/type'):#查找movie下一級(jí)節(jié)點(diǎn)中的所有type標(biāo)簽 ,XPATH的應(yīng)用場(chǎng)景
??? print (elem.tag, elem.attrib)
#type {}
#type {}
#type {}
#type {}
print ("*"*50)
**************************************************
for elem in tree.iter(tag='stars'):#在整個(gè)樹中查找標(biāo)簽為star的元素
??? print (elem.tag, elem.attrib)
#stars {}
#stars {}
#stars {}
#stars {}
print ("*"*50)
#**************************************************
for elem in tree.iterfind('*[@title="Ishtar"]'): #查找屬性為title="Ishtar"的元素,iterfind是個(gè)迭代器
??? print (elem.tag, elem.attrib)
#movie {'title': 'Ishtar'}
print ("*"*50)
#**************************************************
for elem in tree.iterfind('movie[@title="Ishtar"]'): #查找movie下屬性為title="Ishtar"的元素
??? print (elem.tag, elem.attrib)
#movie {'title': 'Ishtar'}
print ("-"*50)
#--------------------------------------------------
root = tree.getroot()???????????????
print ("root:",root[0].tag? )????????? #打印第一級(jí)movie元素的標(biāo)簽,為movie
print ("subnode:",root[0][0].tag)????? #打印第一級(jí)movie元素下的第一個(gè)子元素標(biāo)簽type
print ("subnode:",root[0][1].tag )???? #打印第一級(jí)movie元素下的第二個(gè)子元素標(biāo)簽format
print ("subnode:",root[0][2].tag )???? #打印第一級(jí)movie元素下的第三個(gè)子元素標(biāo)簽year
print ("subnode:",root[0][3].tag )???? #打印第一級(jí)movie元素下的第四個(gè)子元素標(biāo)簽rating
print ("subnode:",root[0][4].tag )???? #打印第一級(jí)movie元素下的第五個(gè)子元素標(biāo)簽stars
del root[0][4] #刪除第一級(jí)movie元素下的第四個(gè)子元素
del root[0][3] #刪除第一級(jí)movie元素下的第三個(gè)子元素
del root[0][2] #刪除第一級(jí)movie元素下的第二個(gè)子元素
del root[0][1] #刪除第一級(jí)movie元素下的第一個(gè)子元素
del root[3] #刪除第四個(gè)movie元素
del root[2] #刪除第三個(gè)movie元素
for subelem in root:
??? print (subelem.tag, subelem.attrib)? #打印四個(gè)movie元素的標(biāo)簽和屬性
tree.write("d:\\movies.xml")? #將變更的xml文件寫入到文件中
?
2) 新建一個(gè)xml 文件:
import sys
try:
??? import xml.etree.cElementTree as ET
except ImportError:
??? import xml.etree.ElementTree as ET
a = ET.Element('elem')??????????? #生成一個(gè)節(jié)點(diǎn)elem,沒有文本節(jié)點(diǎn)
c = ET.SubElement(a, 'child1')??? #生成一個(gè)子節(jié)點(diǎn)下的子節(jié)點(diǎn)child1
c.text = "some text"????????????? #在子節(jié)點(diǎn)上添加文本節(jié)點(diǎn)
d = ET.SubElement(a, 'child2')??? #生成一個(gè)子節(jié)點(diǎn)下的子節(jié)點(diǎn)child2
b = ET.Element('elem_b')????????? #生成一個(gè)節(jié)點(diǎn)elem_b,沒有文本節(jié)點(diǎn)
root = ET.Element('root')???????? #生成一個(gè)節(jié)點(diǎn)root
root.extend((a, b))?????????????? #將a、b兩個(gè)變量存儲(chǔ)的節(jié)點(diǎn)elem和elem1添加到root節(jié)點(diǎn)下
tree = ET.ElementTree(root)?????? #生成節(jié)點(diǎn)樹
root[0].set('foo', 'bar')???????? #設(shè)定第一個(gè)子元素的屬性foo,值為bar
tree.write("d:\\test.xml")??????? #將xml文件內(nèi)容寫入到文本文件中
?
3) 邊讀邊解析xml文件
#coding=utf-8
import sys
try:
??? import xml.etree.cElementTree as ET
except ImportError:
??? import xml.etree.ElementTree as ET
tree = ET.parse("d:\\movies.xml")
count = 0
for elem in tree.iter(tag='movie'): #遍歷樹中的movie節(jié)點(diǎn)
??? print (elem.tag)
??? if elem[0].text == 'War, Thriller':
??????? count += 1
print (count)
#以下代碼實(shí)現(xiàn)了邊讀文件邊解析的作用,節(jié)省了內(nèi)存
count = 0
for event, elem in ET.iterparse("d:\\movies.xml"):? #遍歷所有xml文件中的標(biāo)簽
??? #print (elem.tag)
??? if event == 'end':? #檢測(cè)“閉合的”(end)事件,標(biāo)簽關(guān)閉
??????? if elem.tag == 'type' and elem.text == 'War, Thriller':? #標(biāo)簽為type,且文本內(nèi)容為War, Thriller ,則count+1
??????????? count += 1
??? elem.clear() #清除元素內(nèi)容,不清除則整個(gè)兒樹也會(huì)在內(nèi)存中,沒有起到節(jié)省內(nèi)存的作用。
print (count)
#事件
#start 在元素打開時(shí)觸發(fā)。數(shù)據(jù)和元素的子元素仍不可用。
# end 在元素關(guān)閉時(shí)觸發(fā)。所有元素的子節(jié)點(diǎn),包括文本節(jié)點(diǎn),現(xiàn)在都是可用的。
#close 在解析完成后觸發(fā)。
?
?
小練習(xí):
獲取database.xml文件中的host\username\assword\databasename的值。
databases.xml:
<databaselist type="database config">
<database>
<host>localhost</host>
<username>root</username>
<password>11111</password>
<datasename>wulaoshi</datasename>
</database>
</databaselist>
?
程序:
from xml.dom.minidom import parse ??????#從xml.dom.minidom模塊引入解析器parse
DOMTree = parse(r"e:\databases.xml")?? ?#minidom解析器打開xml文檔并將其解析為內(nèi)存中的一棵樹
databaselist = DOMTree.documentElement
database = databaselist.getElementsByTagName("database")
print(database)
[<DOM Element: database at 0x1e873fa6638>]
d={}
for i in range(1,8,2):
? ? tag_name = database[0].childNodes[i].tagName
? ? d[tag_name]=database[0].childNodes[i].childNodes[0].data
print(d)
{'host': 'localhost', 'username': 'root', 'password': '11111', 'datasename': 'wulaoshi'}
============================
方法1:
for k,v in d.items():
print(k,v)
host localhost
username root
password 11111
datasename wulaoshi
==============================
方法2:
host = d["host"]
username = d["username"]
password = d["password"]
datasename = d["datasename"]
print(host)
==============================
?
轉(zhuǎn)載于:https://www.cnblogs.com/suitcases/p/11043575.html
總結(jié)
以上是生活随笔為你收集整理的python进阶(十七)xml(下)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用AJAX Toolkit创建新闻列表
- 下一篇: python进阶(十七)正则json(上