一、介紹及優(yōu)缺點(diǎn)分析
- DOM(Document Object Model)
DOM是用與平臺(tái)和語(yǔ)言無(wú)關(guān)的方式表示XML文檔的官方W3C標(biāo)準(zhǔn)刑巧。DOM是以層次結(jié)構(gòu)組織的節(jié)點(diǎn)或信息片斷的集合。這個(gè)層次結(jié)構(gòu)允許開(kāi)發(fā)人員在樹(shù)中尋找特定信息斩芭。分析該結(jié)構(gòu)通常需要加載整個(gè)文檔和構(gòu)造層次結(jié)構(gòu)洁闰,然后才能做任何工作。由于它是基于信息層次的皂吮,因而DOM被認(rèn)為是基于樹(shù)或基于對(duì)象的。
【優(yōu)點(diǎn)】
①允許應(yīng)用程序?qū)?shù)據(jù)和結(jié)構(gòu)做出更改税手。
②訪問(wèn)是雙向的蜂筹,可以在任何時(shí)候在樹(shù)中上下導(dǎo)航,獲取和操作任意部分的數(shù)據(jù)芦倒。
【缺點(diǎn)】
①通常需要加載整個(gè)XML文檔來(lái)構(gòu)造層次結(jié)構(gòu)艺挪,消耗資源大。- SAX(Simple API for XML)
SAX處理的優(yōu)點(diǎn)非常類(lèi)似于流媒體的優(yōu)點(diǎn)兵扬。分析能夠立即開(kāi)始麻裳,而不是等待所有的數(shù)據(jù)被處理。而且器钟,由于應(yīng)用程序只是在讀取數(shù)據(jù)時(shí)檢查數(shù)據(jù)津坑,因此不需要將數(shù)據(jù)存儲(chǔ)在內(nèi)存中。這對(duì)于大型文檔來(lái)說(shuō)是個(gè)巨大的優(yōu)點(diǎn)俱箱。事實(shí)上国瓮,應(yīng)用程序甚至不必解析整個(gè)文檔灭必;它可以在某個(gè)條件得到滿足時(shí)停止解析狞谱。一般來(lái)說(shuō),SAX還比它的替代者DOM快許多禁漓。
選擇DOM還是選擇SAX跟衅? 對(duì)于需要自己編寫(xiě)代碼來(lái)處理XML文檔的開(kāi)發(fā)人員來(lái)說(shuō), 選擇DOM還是SAX解析模型是一個(gè)非常重要的設(shè)計(jì)決策播歼。 DOM采用建立樹(shù)形結(jié)構(gòu)的方式訪問(wèn)XML文檔伶跷,而SAX采用的是事件模型掰读。
DOM解析器把XML文檔轉(zhuǎn)化為一個(gè)包含其內(nèi)容的樹(shù),并可以對(duì)樹(shù)進(jìn)行遍歷叭莫。用DOM解析模型的優(yōu)點(diǎn)是編程容易蹈集,開(kāi)發(fā)人員只需要調(diào)用建樹(shù)的指令,然后利用navigation APIs訪問(wèn)所需的樹(shù)節(jié)點(diǎn)來(lái)完成任務(wù)雇初÷K粒可以很容易的添加和修改樹(shù)中的元素。然而由于使用DOM解析器的時(shí)候需要處理整個(gè)XML文檔靖诗,所以對(duì)性能和內(nèi)存的要求比較高郭怪,尤其是遇到很大的XML文件的時(shí)候。由于它的遍歷能力刊橘,DOM解析器常用于XML文檔需要頻繁的改變的服務(wù)中鄙才。
SAX解析器采用了基于事件的模型,它在解析XML文檔的時(shí)候可以觸發(fā)一系列的事件促绵,當(dāng)發(fā)現(xiàn)給定的tag的時(shí)候攒庵,它可以激活一個(gè)回調(diào)方法,告訴該方法制定的標(biāo)簽已經(jīng)找到败晴。SAX對(duì)內(nèi)存的要求通常會(huì)比較低叙甸,因?yàn)樗岄_(kāi)發(fā)人員自己來(lái)決定所要處理的tag.特別是當(dāng)開(kāi)發(fā)人員只需要處理文檔中所包含的部分?jǐn)?shù)據(jù)時(shí),SAX這種擴(kuò)展能力得到了更好的體現(xiàn)位衩。但用SAX解析器的時(shí)候編碼工作會(huì)比較困難裆蒸,而且很難同時(shí)訪問(wèn)同一個(gè)文檔中的多處不同數(shù)據(jù)。
【優(yōu)勢(shì)】
①不需要等待所有數(shù)據(jù)都被處理糖驴,分析就能立即開(kāi)始僚祷。
②只在讀取數(shù)據(jù)時(shí)檢查數(shù)據(jù),不需要保存在內(nèi)存中贮缕。
③可以在某個(gè)條件得到滿足時(shí)停止解析辙谜,不必解析整個(gè)文檔。
④效率和性能較高感昼,能解析大于系統(tǒng)內(nèi)存的文檔装哆。
【缺點(diǎn)】
①需要應(yīng)用程序自己負(fù)責(zé)TAG的處理邏輯(例如維護(hù)父/子關(guān)系等),文檔越復(fù)雜程序就越復(fù)雜定嗓。
②單向?qū)Ш酵汕伲瑹o(wú)法定位文檔層次,很難同時(shí)訪問(wèn)同一文檔的不同部分?jǐn)?shù)據(jù)宵溅,不支持XPath凌简。
二、解析xml dom
- SAX(Simple API for XML)
// 解析xml sax
func parseXml() {
let path = Bundle.main.path(forResource: "index", ofType: "xml")
let url = URL(fileURLWithPath: path!)
let data = try! Data(contentsOf: url)
print(data)
// 創(chuàng)建xmlparser對(duì)象
let xmlParser = XMLParser(data: data)
xmlParser.delegate = self // delegate
xmlParser.parse() // 開(kāi)始解析
}
// XMLParserDelegate
// 開(kāi)始解析
var arr: [Student]? = nil
func parserDidStartDocument(_ parser: XMLParser) {
print("開(kāi)始解析")
// 初始化數(shù)組
arr = [Student]()
}
// 獲取標(biāo)簽
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
print("name = " + elementName)
// 當(dāng)發(fā)現(xiàn)student節(jié)點(diǎn)的時(shí)候,創(chuàng)建Student對(duì)象
if elementName == "student" {
let stu = Student()
arr?.append(stu) // 存到到數(shù)組中
}
currentElement = elementName;
}
// 創(chuàng)建一個(gè)全局變量來(lái)傳遞節(jié)點(diǎn)
var currentElement: String? = nil
// 獲取值
func parser(_ parser: XMLParser, foundCharacters string: String) {
// 去除空字符串
let str = string.trimmingCharacters(in: .whitespacesAndNewlines)
if str == "" || str.isEmpty {
return
}
print("String = " + string)
// 如果是name節(jié)點(diǎn)
if "name" == currentElement {
arr?.last?.name = str
} else if ("age" == currentElement) {
arr?.last?.age = Int(str)
}
}
// 結(jié)束解析
func parserDidEndDocument(_ parser: XMLParser) {
print("結(jié)束解析")
for item in arr! {
print("item.name = \(item.name) item.age = \(item.age)")
}
}
三恃逻、 解析xml dom
// 解析xml dom
func domXMl() {
let path = Bundle.main.path(forResource: "index", ofType: "xml")
let url = URL(fileURLWithPath: path!)
let data = try! Data(contentsOf: url)
let dataXml = try! GDataXMLDocument(data: data, options: 0)
// 獲取根節(jié)點(diǎn)
let element = dataXml.rootElement() //Students
// 獲取子節(jié)點(diǎn)
let arr = element?.children() as! [GDataXMLElement] // Student
var StuArr:[Student] = [Student]() // 創(chuàng)建一個(gè)數(shù)組裝Student對(duì)象
for stu in arr { // stu 每一個(gè)student節(jié)點(diǎn)
let stuent = Student()
// 獲取name節(jié)點(diǎn)
let ele = stu.elements(forName: "name") as![GDataXMLElement]
stuent.name = ele.first?.stringValue()
let ageEle = stu.elements(forName: "age") as![GDataXMLElement]
stuent.age = Int((ageEle.first?.stringValue())!)
StuArr.append(stuent)
}
for item in StuArr {
print("stu.name = \(item.name) stu.age = \(item.age)")
}
}
注意繼承 XMLParserDelegate