SwiftのXMLParserはイベント駆動のparser。
import UIKit
class ParserSample: NSObject {
private let parser: XMLParser
init(data: Data) {
parser = XMLParser(data: data)
super.init()
parser.delegate = self
}
func parse() {
guard parser.parse() else {
guard let err = parser.parserError else {
print("parse error but unknown reason")
return
}
print("parse error: \(err.localizedDescription)")
return
}
print("after parse()")
}
}
XMLParserDelegateでイベントを拾ってオブジェクトに詰めるなりする。全て実装する必要はなく、この例ではタグの開始と文字列、CDATA、エラー、パース終了時の関数を実装している。
extension ParserSample: XMLParserDelegate {
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
print("parsing <\(elementName)>")
if elementName == "ERROR" {
self.parser.abortParsing() // test
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
print("found \(string)")
}
func parser(_ parser: XMLParser,
foundCDATA CDATABlock: Data) {
let data = String(bytes: CDATABlock, encoding: .utf8)
print("foundCDATA \(data!)")
}
func parser(_ parser: XMLParser, parseErrorOccurred parseError: Error) {
print("parser error: \(parseError.localizedDescription)")
}
func parserDidEndDocument(_ parser: XMLParser) {
print("parse done")
}
}
最後まで正常にパースされる場合と、途中で中断される場合を実行する。
print("-- case 1 (success) --")
guard let data1 = "<A><B>\n<D>value</D></B><C><![CDATA[ccccc]]></C></A>".data(using: .utf8) else {
print("cast to data1 error")
exit(1)
}
ParserSample(data: data1).parse()
print("-- case 2 (abort) --")
guard let data2 = "<ERROR></ERROR>".data(using: .utf8) else {
print("cast to data2 error")
exit(1)
}
ParserSample(data: data2).parse()
最後までパースするとparserDidEndDocument()
が実行された後parse()
がtrueを返し、
途中で中断するとparseErrorOccurred
の関数が呼ばれてparse()
がfalseを返す。
-- case 1 (success) --
parsing <A>
parsing <B>
found
parsing <D>
found value
parsing <C>
foundCDATA ccccc
parse done
after parse()
-- case 2 (abort) --
parsing <ERROR>
parser error: The operation couldn’t be completed. (NSXMLParserErrorDomain error 512.)
parse error: The operation couldn’t be completed. (NSXMLParserErrorDomain error 512.)