Help us understand the problem. What is going on with this article?

SwiftでHTMLを構文解析して、UITableViewにマッピングする方法

More than 3 years have passed since last update.

最初に

この記事は、SwiftHTMLを構文解析する方法を記載した記事です。
記載時(2015/12/06)のバージョンは下記の通りです。

対象 バージョン
Swift 2.1
Ono 1.2.2
XCode 7.1.1
Mac 10.11.1

最後に今回のサンプルコードをGitHubにあげております。
(あまり綺麗なコードじゃないかもしれないですが、参考程度にしてもらえればと思います)

なぜWebViewを使わずに、UITableViewにマッピングするのか

理由はデザインを統一させたいというのが一番です。
あとはOnoの作者であるMatttさんが復活したということで、
今回Onoについてご紹介したかったのが大きいです(-∀-)
この記事は、マッピング方法を記載しておりますが、
HTMLの構文解析だけを行いたい場合でも、参考になると思います。

実装方法

ライブラリ導入

https://github.com/mattt/Ono#podfile
Onoをプロジェクトに導入します。

動作確認

以下のようにOnoをImportして、利用することが出来れば問題なく導入できている思います。

import Ono
<省略>
let document = try ONOXMLDocument.HTMLDocumentWithString("<html><body>hoge</body></html>", encoding: NSUTF8StringEncoding)

実装のポイント①:許可するタグを選定する

HTMLには様々なタグが存在しますが、全てに準拠しようとすると大変です。
なので、許可するタグを管理するEnumを作成します。
今回は文章の基本構成を表す
<p>,<h1>,<h2>,<h3> を許可することにします。

enum PermitTag: String {
    case none = ""
    case p = "p"
    case h1 = "h1"
    case h2 = "h2"
    case h3 = "h3"
}

上記のEnumを利用し、パース処理を行う時にタグの選定を行います

for element in bodyElement.children {
    if let element = element as? ONOXMLElement {
        // 許可しているタグのみパースする
        if let tag = PermitTag(rawValue: element.tag) {
            parseElement(element, tag: tag)
        }
    }
}

実装のポイント②:タグごとに対応するUITableViewCellのカスタムクラスを作成する

タグごとに対応するUITableViewCellのカスタムクラスを作成し、
cellForRowAtIndexPathで、それぞれに合う型変換を行う

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let element = elements[indexPath.row]
        let identifier = element.tag.rawValue.uppercaseString + "TagTableViewCell"

        switch element.tag {
        case .p:
            let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath) as! PTagTableViewCell
            cell.body = element.value
            return cell
        case .h1:
            let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath) as! H1TagTableViewCell
            cell.body = element.value
            return cell
        case .h2:
            let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath) as! H2TagTableViewCell
            cell.body = element.value
            return cell
        case .h3:
            let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath) as! H3TagTableViewCell
            cell.body = element.value
            return cell
        default:
            return UITableViewCell()
        }
    }

Qiitaの記事を取り込んで、動作確認

demo

※ 今回はhtmlファイルをローカルに落とし込んで、さらに記事本文の部分だけを抜き出しています。パース処理 & マッピングにフォーカスするために、webから取得する部分を省きました。

感想

ニュースアプリを見ていると、
本文部分だけWebViewなのを見ると少しがっかり感ありますよね。
UITableViewでマッピングしてやると、表示漏れが出てきたり、
今後新しいタグが増えたらどうするんだ?とか色々懸念点はありますが・・
逆に指定したタグ以外は絶対に表示されないというメリットもあります。

とりあえず、言えることはこの記事需要なさそうである。(書いてて薄々気付いていた)
もし、要望があれば<a>,<strong>,<img>も対応した記事を書こうかなと思っています...('_`)

GitHub : https://github.com/bpyamasinn/MappingToTableView

引用元

Ono:https://github.com/mattt/Ono
Qiitaのサンプルに用いたページ SwiftLint導入もよろしくお願いします:http://qiita.com/syamaoka/items/2edfe315940d91846bf0

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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした