XML和XML解析
一、什麼是XML
XML 指可擴充标記語言(EXtensible Markup Language)
XML 是一種标記語言,很類似 HTML
XML 的設計宗旨是傳輸資料,而非顯示資料
XML 标簽沒有被預定義。您需要自行定義标簽。
XML 被設計為具有自我描述性。
XML 是 W3C 的推薦标準。
要注意的是,XML不做任何事情,它隻是用來存儲和傳輸資料的。
比如:
<?xml version="1.0" encoding="utf-8"?>
#DTD 的作用是定義在某個 XML 文檔中那些元素和屬性是合法的。
#DTD 被用來驗證 XML 資料。
<!DOCTYPE students [
<!ELEMENT students (student+)>
<!ELEMENT student (stuname,stuage,stusex)>
<!ELEMENT stuname (#PCDATA)>
<!ELEMENT stuage (#PCDATA)>
<!ELEMENT stusex (#PCDATA)>
<!ATTLIST student id CDATA #REQUIRED>
]>
<students>
<student id="1">
<stuname>張三</stuname>
<stuage>21</stuage>
<stusex>男</stusex>
</student>
<student id="2">
<stuname>李靜</stuname>
<stuage>20</stuage>
<stusex>女</stusex>
</student>
</students>
如上,就是一個XML格式的檔案。
我們可以看到,基本和HTML檔案格式差不多:
XML配置檔案固定格式:
1.标簽成對出現
2.區分大小寫
3.标簽要正确嵌套
4.開始部分
<?xml version="1.0" encoding="utf-8"?>
5.隻能有一個根節點
6.節點可以有屬性
二、XML解析
1.sax解析
python 标準庫包含SAX解析器,SAX用事件驅動模型,通過在解析XML的過程中觸發一個個的事件并調用使用者定義的回調函數來處理XML檔案。
SAX是一種基于事件驅動的API。
利用SAX解析XML文檔牽涉到兩個部分:解析器和事件處理器。
解析器負責讀取XML文檔,并向事件處理器發送事件,如元素開始跟元素結束事件;
而事件處理器則負責對事件作出相應,對傳遞的XML資料進行處理。
1、對大型檔案進行處理;
2、隻需要檔案的部分内容,或者隻需從檔案中得到特定資訊。
3、想建立自己的對象模型的時候。
在python中使用sax方式處理xml要先引入xml.sax中的parse函數,還有xml.sax.handler中的ContentHandler。
ContentHandler類方法介紹
characters(content)方法
調用時機:
從行開始,遇到标簽之前,存在字元,content的值為這些字元串。
從一個标簽,遇到下一個标簽之前, 存在字元,content的值為這些字元串。
從一個标簽,遇到行結束符之前,存在字元,content的值為這些字元串。
标簽可以是開始标簽,也可以是結束标簽。
startDocument()方法
文檔啟動的時候調用。
endDocument()方法
解析器到達文檔結尾時調用。
startElement(name, attrs)方法
遇到XML開始标簽時調用,name是标簽的名字,attrs是标簽的屬性值字典。
endElement(name)方法
遇到XML結束标簽時調用。
代碼如下:
XML檔案同上,以下代碼是用SAX方法解析
from xml.sax import parse
from xml.sax.handler import ContentHandler
stulist=[]
class Stu:
def __init__(self,id=None,name=None,age=None,sex=None):
self.id=id
self.name=name
self.age=age
self.sex=sex
def __repr__(self):
return self.id+"\t"+self.name+"\t\t"+self.age+"\t"+self.sex
class SaxParser(ContentHandler):
def __init__(self,name=None):
self.name=name
self.stu=None
def startDocument(self):
print("startDocument")
def endDocument(self):
print("endDocument")
def startElement(self, name, attrs):
if name=="student":
self.stu=Stu()
self.stu.id=attrs['id']
self.name=name
def characters(self, content):
if self.name=="stuname":
self.stu.name=content
#print(content)
elif self.name=="stuage":
self.stu.age=content
#print(content)
elif self.name=="stusex":
self.stu.sex=content
##print(content)
def endElement(self, name):
if name=="student":
stulist.append(self.stu)
self.name=None
parse("XML.xml",SaxParser())
print(stulist)
以上代碼就是通過重寫ContentHandler類的方法來實作對XML檔案的解析。
2.DOM解析
一個 DOM 的解析器在解析一個XML文檔時,一次性讀取整個文檔,把文檔中所有元素儲存在記憶體中的一個樹結構裡,之後你可以利用DOM 提供的不同的函數來讀取或修改文檔的内容和結構,也可以把修改過的内容寫入xml檔案。python中用xml.dom.minidom來解析xml檔案。
from xml.dom.minidom import parse
stus=parse("XML.xml")
#擷取檔案根節點
root=stus.documentElement
print(root)
students=root.getElementsByTagName("student")
stulist=[]
for i in students:
name=i.getElementsByTagName("stuname")[].childNodes[].data
age = i.getElementsByTagName("stuage")[].childNodes[].data
sex = i.getElementsByTagName("stusex")[].childNodes[].data
id=i.getAttribute("id")
print(name,age,sex,id)
student={"學号":id,"姓名":name,"年齡":age,"性别":sex}
stulist.append(student)
print(stulist)
- 第一個 stuname 元素
getElementsByTagName("stume")[0]
- stuname 元素的第一個子節點 (文本節點)
childNodes[0]
- 就是具體的文本資料了
data
常用的一些DOM屬性有:
x.nodeName - x 的名稱
x.nodeValue - x 的值
x.parentNode - x 的父節點
x.childNodes - x 的子節點
x.attributes - x 的屬性節點
注意:
x 是一個節點對象。
常用的一些DOM方法:
.getElementsByTagName(name) - 擷取帶有指定标簽名稱的所有元素
.getElementById(id) :傳回對擁有指定 id 的第一個對象的引用。
3.ElementTree
ElementTree生來就是為了處理XML,它在Python标準庫中有兩種實作:一種是純Python實作的,如xml.etree.ElementTree,另一種是速度快一點的xml.etree.cElementTree。注意:盡量使用C語言實作的那種,因為它速度更快,而且消耗的記憶體更少。
try:
import xml.etree.cElementTree as ET
except ImportError:
import xml.etree.ElementTree as ET
stulist=[]
class Stu:
def __init__(self,id=None,name=None,age=None,sex=None):
self.id=id
self.name=name
self.age=age
self.sex=sex
def __repr__(self):
return self.id+"\t"+self.name+"\t\t"+self.age+"\t"+self.sex
def tset():
tree=ET.parse("XML.xml")
#root=tree.getroot()擷取根節點
students=tree.findall("student")
for stu in students:
student=Stu()
student.id=stu.attrib["id"]
#獲根節點下的所有子節點
children=stu.getchildren()
student.name=children[].text
student.age=children[].text
student.sex=children[].text
stulist.append(student)
tset()
print(stulist)
Elementtree解析XML檔案的過程就是:
1.導入ElementTree,import xml.etree.ElementTree as ET
2.解析Xml檔案找到根節點: 直接解析XML檔案并獲得根節點,
tree = ET.parse(‘XML檔案’)
root = tree.getroot()
3.周遊根節點可以獲得子節點,然後就可以根據需求拿到需要的字段了。