Swift5 XMLParserを使ってXML解析をする②

結構期間が空いてしまいましたが、前回の続きです。今回は以前に紹介したメソッドを使ってパースしたデータを表示するだけの簡単なアプリを作ります。まだ前回を見ていない方は下記リンクをどうぞ。

**[Swift5 XMLParserを使ってXML解析をする①](https://qiita.com/Tack2770/items/5f67d4625da379a41679)**

今回使ったデータは総務省：電子政府の総合窓口から頂きました。

##はじめに
今回の流れを説明します。

　**１．完成形の画像を見せます。**（表示するだけなのでめっちゃショボいです。）
　**２．今回作ったメソッドの使い方を説明します。
　３．今回使ったメソッドで理解が難しいところを説明します。
　４．感想**


以上です。それでは行きましょう。


##１．今回の完成形

これが完成形です。あまりにも．．．って感じですが、パースのメソッド紹介で作った物なので、勘弁してください。

どうでもいい事ですけど、スクショのコマンドって覚えにくいですね。
あとシュミレータがiPod touchって．．．
![スクリーンショット 2021-03-12 23.50.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/657690/9fb91b1e-0fec-e5bd-9615-314d2a576302.png)

##２．パースで使うメソッドの説明

今回使ったメソッドは前回紹介したものの内、下記の５つです。（長いので省略しています。）
　**①parser(..didStartElement
　②parser(..foundCharacters
　③parser(..didEndElement
　④parserDidEndDocument
　⑤parse()**
表示するだけならこの位でできてしまうんですよね。結構簡単です。

###①didStartElement
これはパースを始める時に動くメソッドです。
ちなみにこれはデリゲートメソッドなので、viewDidLoad()でデリゲート宣言してください。

実際の記述はこんな感じです。

```swift:
    func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
        if elementName == "LawNameListInfo"{
            self.lawTableView.append(LawItems())
        }else{
            lawName = elementName
        }
    }
```

いきなり引数多めですが、予測変換で出たものを何もいじっていませんので全く焦る必要はないです。実際に書くのは{ }内だけです。lawNameは他のメソッドとの間を行き交うので、グローバル変数で宣言します。**ここでやることはこの後にパースした要素が入る配列を用意する事**です。これをやっておかないと、要素が入る配列がないのでエラーになります。

###②foundCharacters
ここでは欲しい要素があった時にどうするかを記述します。

```swift:
    func parser(_ parser: XMLParser, foundCharacters string: String) {
        if self.lawTableView.count > 0{
            let getLawItem = self.lawTableView[self.lawTableView.count - 1]  
            switch self.lawName{
            case "LawName":
                getLawItem.lawElement = string
            case .none:
                break
            case .some(_):
                break
            }
        }
    }
```

パースした情報の中に欲しい情報（ここでは"LawName"）があった時、配列に値を入れています。**パースしたデータには全てタグ（見出し）が振られています。上から順にパースしていき、その該当する見出しが来たときに、その中に入っている値を配列に入れればいいのです。**
ということで見出しがLawNameの時に配列を入れるようにします。

なぜifを使ってるのかというと、didStartElementで作る配列がある時のみ起動するようにする為です。

また配列は０から始まる為、−１をして合わせています。

###③didEndElement
ここではエレメントの処理が終わった時に処理を記述する時に使います。
**やる事は次のパースをする為に変数を空にします。**


```swift:
    func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
        self.lawName = nil
    }
```


###④parserDidEndDocument
パースの処理が終わった時に処理を記述する時に使います。
**ここでは、配列に格納したデータをテーブルビューなどに表示するときに使います。**


```swift:
    func parserDidEndDocument(_ parser: XMLParser) {
        XMLTableView?.reloadData()
    }
```
reloadData()はviewDidLoad()内でも記述はできますが、かなり処理速度は落ちます。また速度をあまり落とさない事もできますが少し書き加える為、わざわざそうする必要もないと思います。

###⑤parse
これをviewDidLoad()内に記述しないと何も始まりません。
必ず書きます。

```swift:
   lawParser.parse()
```

##３．今回の難所
まあ特にはないんですけど、超基礎の部分の理解は必要になります。
例えば、②のgetLawItem.lawElement = stringなんかは**参照渡しなどの理解がないと難しい**と思います。

参考になるかならないか微妙ですが、以前参照渡しの記事も書いたのでご覧下さい。
 **[Swift5　引数の参照渡し](https://qiita.com/Tack2770/items/9214487fe031846c286d)**

また配列の−１の部分にカウントとのずれがあるところなども基本的な理解がないと厳しいし、他にはどの変数をグローバル変数にするかなども、全く知らない状態だと解決が難しいです。

##４．感想
今回は表示する以外何も実装しませんでしたが、タップした時の動作や、検索機能などを実装するだけでもかなりアプリっぽくなると思います。
コード全文は参考にしたい人がいるのなら（いるのかな？）貼ろうかなと思います。（特に何かしてるわけではないのでかなり短いですが．．．）

何か間違いがありましたらご連絡いただければ幸いです。


以上で終わります。ありがとうございました。