Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

軽くて、素早くて、 Swift の XML/HTML パーサー

More than 3 years have passed since last update.

Fuzi

私が作ったXML/HTML パーサーFuziがSwiftSandbox Issue 9に当選しましたw

Update: 2016/09/24, FuziがFirefox for iOSプロジェクトに採用されました

Fuzi は Mattt Thompson氏の Ono(斧) に参照し Swift 言語で実装した XML/HTML パーサーです。[ドキュメント]

よろしければ、どうぞお使いくださ(CocoaPods, Carthage対応あり)

https://github.com/cezheng/Fuzi

日本語のREADMEもあります https://github.com/cezheng/Fuzi/blob/master/README-ja.md

用例

XML

import Fuzi

let xml = "..."
do {
  // if encoding is omitted, it defaults to NSUTF8StringEncoding
  let doc = try XMLDocument(string: xml, encoding: NSUTF8StringEncoding)
  if let root = document.root {
    print(root.tag)

    // define a prefix for a namespace
    document.definePrefix("atom", defaultNamespace: "http://www.w3.org/2005/Atom")

    // get first child element with given tag in namespace(optional)
    print(root.firstChild(tag: "title", inNamespace: "atom")

    // iterate through all children
    for element in root.children {
      print("\(index) \(element.tag): \(element.attributes)")
    }
  }
  // you can also use CSS selector against XMLDocument when you feels it makes sense
} catch let error as XMLError {
  switch error {
  case .NoError: print("wth this should not appear")
  case .ParserFailure, .InvalidData: print(error)
  case .LibXMLError(let code, let message):
    print("libxml error code: \(code), message: \(message)")
  }
}

HTML

HTMLDocumentXMLDocument サブクラス。

import Fuzi

let html = "<html>...</html>"
do {
  // if encoding is omitted, it defaults to NSUTF8StringEncoding
  let doc = try HTMLDocument(string: html, encoding: NSUTF8StringEncoding)

  // CSS queries
  if let elementById = doc.css("#id") {
    print(elementById.stringValue)
  }
  for link in doc.css("a, link") {
      print(link.rawXML)
      print(link["href"]
  }

  // XPath queries
  if let title = doc.firstChild(xpath: "//head/title") {
    print(title.stringValue)
  }
  for paragraph in doc.xpath(".//body/descendant::p") {
    print(meta["class"])
  }

  // Evaluate XPath functions
  if let result = doc.eval(xpath: "count(/*/a)") {
    print("anchor count : \(result.doubleValue)")
  }
} catch let error {
  print(error)
}

エラー処理なんて、どうでもいい場合

import Fuzi

let xml = "..."

// Don't show me the errors, just don't crash
if let doc1 = try? XMLDocument(string: xml) {
  //...
}

let html = "<html>...</html>"

// I'm sure this won't crash
let doc2 = try! HTMLDocument(string: html)
//...

Onoからの移行?

下記2つのサンプルコードを見たら、OnoFuziの違いをわかる。

Onoサンプル

Fuziサンプル

もっと詳しい情報はgithubのREADMEをご覧ください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away