標籤:
//// main.swift// C150805_libxml2r2// http://git.oschina.net/yao_yu/Swift2015/tree/master/C150805_libxml2r2?dir=1&filepath=C150805_libxml2r2&oid=f80a7498226526b991e7913298c15cd38480aea5&sha=c073af33d0534a10098bb8fcc0706c2fd489dc3f//// Created by yao_yu on 15/8/5.// Copyright © 2015年 yao_yu. All rights reserved.//import Foundation/* ---------- 擴充 ---------- */extension NSString{ convenience init?(urlString:String, encoding:NSStringEncoding) { let url = NSURL(string: urlString) do { try self.init(contentsOfURL: url!, encoding: encoding) } catch {} }}extension String { init?(XMLChar char: UnsafePointer<xmlChar>){ self.init() if char != nil { self = String.fromCString(UnsafePointer<CChar>(char))! } }}/* ---------- XML節點 ---------- */class XMLNode { var xmlDoc:xmlDocPtr = nil var xmlNode:xmlNodePtr = nil init(node:xmlNodePtr, document:xmlDocPtr) { self.xmlNode = node self.xmlDoc = document } convenience init(document:xmlDocPtr) { self.init(node:xmlDocGetRootElement(document), document:document) } lazy var rawContent:String? = { return XMLNodeGetContent(self.xmlNode)// return XMLNodeGetString(self.xmlDoc, xmlNode: self.xmlNode) }() lazy var children:[XMLNode] = { return self.xmlNodes2XMLNodes(XMLNodeGetChildren(self.xmlNode)) }() lazy var attributes: [String: String] = { return XMLNodeGetAttributes(self.xmlNode) }() subscript(key:String) -> String? { return attributes[key] } private func xmlNodes2XMLNodes(nodes:[xmlNodePtr]) -> [XMLNode] { var xmlNodes = [XMLNode]() for node in nodes{ xmlNodes.append(XMLNode(node: node, document: xmlDoc)) } return xmlNodes //下面的代碼引發:Command failed due to signal: Abort trap: 6 //return nodes.map{[unowned self] in XMLNode(node:$0, document:self.xmlDoc)} }}extension XMLNode { func xPath(xpath: String) -> [XMLNode] { return xmlNodes2XMLNodes(XMLFindXPath(self.xmlDoc, xPath: xpath)) }}/* ---------- libxml2讀取工具函數 ---------- */func XMLNodeGetString(doc:xmlDocPtr, xmlNode:xmlNodePtr) -> String? { let contentChars = xmlNodeListGetString(doc, xmlNode, 1) if contentChars == nil { return nil } let contentString = String(XMLChar: contentChars) free(contentChars) assert(contentString != nil, "XMLNodeGetString: 值轉換不成功") return contentString}func XMLNodeGetContent(xmlNode:xmlNodePtr) -> String? { let contentChars = xmlNodeGetContent(xmlNode) if contentChars == nil { return nil } let contentString = String(XMLChar: contentChars) free(contentChars) assert(contentString != nil, "XMLNodeGetContent: 值轉換不成功") return contentString}func XMLNodeGetChildren(xmlNode: xmlNodePtr) -> [xmlNodePtr] { var children = [xmlNodePtr]() for var childNodePointer = xmlNode.memory.children; childNodePointer != nil; childNodePointer = childNodePointer.memory.next { if xmlNodeIsText(childNodePointer) == 0 { children.append(childNodePointer) } } return children}func XMLNodeGetAttributes(xmlNode: xmlNodePtr) -> [String: String] { var result:[String: String] = [String: String]() for var attribute: xmlAttrPtr = xmlNode.memory.properties; attribute != nil; attribute = attribute.memory.next { if let key:String = String(XMLChar: attribute.memory.name) { if let value:String = XMLNodeGetContent(attribute.memory.children) { result[key] = value } else { result[key] = "" } } else { print((">>>>>>>>>>>>>>>>>>>>>>>>錯誤:", String(XMLChar: attribute.memory.name))) } } return result}func XMLNodeGetAttribute(xmlNode: xmlNodePtr, key: String) -> String? { for var attribute: xmlAttrPtr = xmlNode.memory.properties; attribute != nil; attribute = attribute.memory.next { if key == String(XMLChar: attribute.memory.name) { return XMLNodeGetContent(attribute.memory.children) } } return nil}func XMLFindXPath(xmlDoc:xmlDocPtr, xPath: String) -> [xmlNodePtr] { let xPathContext = xmlXPathNewContext(xmlDoc) if xPathContext == nil { return [] } xPathContext.memory.node = nil let xPathObject = xmlXPathEvalExpression(UnsafePointer<xmlChar>(xPath.cStringUsingEncoding(NSUTF8StringEncoding)!), xPathContext) xmlXPathFreeContext(xPathContext) if xPathObject == nil { return [] } let nodeSet = xPathObject.memory.nodesetval if nodeSet == nil || nodeSet.memory.nodeNr == 0 || nodeSet.memory.nodeTab == nil { xmlXPathFreeObject(xPathObject) return [] } var resultNodes = [xmlNodePtr]() for i in 0 ..< Int(nodeSet.memory.nodeNr) { resultNodes.append(nodeSet.memory.nodeTab[i]) } xmlXPathFreeObject(xPathObject) return resultNodes}func XMLReadNSData(data:NSData?, encoding:NSStringEncoding = NSUTF8StringEncoding, isXML:Bool = false) -> xmlDocPtr? { if let data = data { let cBuffer = UnsafePointer<CChar>(data.bytes) let cSize = CInt(data.length) //// let cfEncoding = CFStringConvertNSStringEncodingToEncoding(encoding)// let cfEncodingAsString:CFStringRef = CFStringConvertEncodingToIANACharSetName(cfEncoding)// let cEncoding:UnsafePointer<CChar> = CFStringGetCStringPtr(cfEncodingAsString, CFStringEncoding(0)) if isXML { let options = CInt(XML_PARSE_RECOVER.rawValue) return xmlReadMemory(cBuffer, cSize, nil, nil, options) } else { let options = CInt(HTML_PARSE_RECOVER.rawValue | HTML_PARSE_NOWARNING.rawValue | HTML_PARSE_NOERROR.rawValue) return htmlReadMemory(cBuffer, cSize, nil, nil, options) } } return nil}let GB18030_2000_Encoding = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(CFStringEncodings.GB_18030_2000.rawValue))/* ---------- 測試代碼 ---------- */class CElapseTime { var startTime:NSDate var prompt:String var unsed:Bool = false init(prompt:String) { self.startTime = NSDate() self.prompt = prompt } var newprompt:String { return "\(prompt)耗時:\(NSDate().timeIntervalSinceDate(startTime))" }}func testParseSina() { var sURL:String var encoding:UInt (sURL,encoding) = ("http://www.baidu.com", NSUTF8StringEncoding) print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\(sURL)") var timer = CElapseTime(prompt: "讀取網頁") //let sContent = NSString(urlString:sURL, encoding: encoding) var sContent:NSString? = nil do{ try sContent = NSString(contentsOfFile: "/Volumes/Data/Document/Test/sample.txt", encoding: NSUTF8StringEncoding) } catch { } print(timer.newprompt) let sTimer1 = timer.newprompt timer = CElapseTime(prompt: "資料解析") if let doc = XMLReadNSData(sContent?.dataUsingEncoding(NSUTF8StringEncoding)){ let rootNode = XMLNode(document: doc) let findNodes = rootNode.xPath("//div") for childNode in findNodes { autoreleasepool{ let _ = (childNode.attributes, childNode.rawContent) }// if let content = childNode.rawContent {// print(content)// } } print(findNodes.count) } print(sTimer1) print(timer.newprompt)}testParseSina()
在Swift中使用libxml2