Posted at

【Swift】NSXMLParserで文字列にアルファベットや数字、マルチバイト文字が含まれる場合、複数に分かれてパースされる件

More than 3 years have passed since last update.

SwiftでXMLをパースする際に、

NSXMLParserを使用するのですが、以下のような要素をパースする際に



<ele>aaa あいうえお abcd 春夏秋冬 123</ele>

マルチバイト+アルファベット文字列が要素内であったとすると、

それぞれ分かれて、一回目aaaで二回目あいうえお、三回目abcdの形で取得できてしまって、

一気に取れないのが不便。

フラグとかはないので手動で配列に貯めてから、閉じタグを読み込んだ時にreduceで再帰的に足して取得する


実装

NSXMLParserDelegateを指定

    var isTitle:Bool=false

var parsedStrArr:Array<String>!
var entries : NSMutableArray!
var tmpEntry : NSMutableArray!

override func viewDidLoad() {
super.viewDidLoad()
loadRss()
}

func loadRss() {

// Sample feed url
let rUrl: NSURL = NSURL(string: "https://hoge.co.jp/feed/?cat=5")!
let rssUrl = rUrl

parser = NSXMLParser(contentsOfURL: rssUrl)!
parser.delegate = self

//以下の1行の処理でparse関連の処理が行われる。
let success:Bool = parser.parse()
if success {
print("パース成功")
} else {
print("パース失敗")
}
}

// NSXMLParserDelegate
// ここから下はParse関連処理

func parserDidStartDocument(parser: NSXMLParser){
entries = NSMutableArray()
}

// 開始タグを読み込んだ時よばれる - Start
func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [NSObject : AnyObject]) {

parsedStrArr = []

if (elementName == "title"){
// 配列初期化
tmpEntry = NSMutableArray()
entries.addObject(tmpEntry)
isTitle = true;
}
}

//閉じタグを読み込んだ時よばれる - End
func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {

if (elementName == "title"){
// reduceによる再帰処理で文字列を足す
tmpEntry.addObject(parsedStrArr.reduce(String()) { $0 + $1 })
isTitle = false
}
}

//タグ以外のテキストを読み込んだ時(タグとタグ間の文字列)
func parser(parser: NSXMLParser, foundCharacters string: String?) {

if(isTitle && tmpEntry != nil){
// タイトル内文字列を追加していく
parsedStrArr.append(string!)
}
}

func parserDidEndDocument(parser: NSXMLParser){
// ここで最終処理 entries
}


参考

[iOS] NSXMLParser で文字列が1つのエレメントで複数に分かれてパースされる

http://www.kuma-de.com/blog/2012-07-20/3782