nimを使ってXMLファイルをパースする為の日本語情報があまりないので、「xmlparser」モジュールを使ってのXMLファイルのパースについて記事にします
色々苦労しましたが、なんとか思い通りの動きができるようになりました
目次
xmlparserモジュールの仕様
以下のリンクにて説明があります(英語)
XMLParserの仕様
使用例
parsexml - |
といっても、所詮英語…一応以下のような仕様です
xmlをロードする
import os, streams, parsexml, strutils var filename = "something.xml" var s = newFileStream(filename, fmRead) if s == nil: quit("cannot open the file " & filename) var x: XmlParser open(x, s, filename)
XmlParserがFileStreamをオ−プンしています
ノードを読み込む
xmlparserは、nextで次のノードに移ります
ループさせて、EOFまで読み込みます
xp.kindによって処理を分岐させる形になります
xp.next block mainLoop: while true: case xp.kind of xmlElementStart: echo "element Start!" xp.next of xmlElementOpen: echo "element Open!" xp.next of xmlEof: break # end of file reached of xmlError: echo(errorMsg(xp)) xp.next() else: xp.next() # skip other events
上記の例だと、EOF(xmlEof)まで無限ループを回して、xmlEofを見つけたら、ブレイクするという流れになります
kindは、以下のようなものがあります。よく使うものから順に紹介すると以下の通り
kindの名前 | 内容 | 例 |
---|---|---|
xmlElementStart | XMLの構成要素の開始を示します(”>”までを取得 | < elem > |
xmlElementEnd | XMLの構成要素の終了そ示す(”>”までを取得 | < /elem > |
xmlElementOpen | XMLの構成要素の開始を示す(”>”までを取得しない | < /elem |
xmlElementClose | Openで取得した構成要素の”>”を取得する | > |
xmlAttribute | Openで取得した構成要素の中にあるアトリビュートを取得 | key=”value” |
xmlCharData | 文字列データ | テキスト |
xmlError | エラーが起きたときの | N/A |
xmlEOF | ファイルの終了 | N/A |
詳細は、以下の英語の説明にあるのですが、とりあえず上記さえあれば、なんとかコントロールできます
xmlElementStartとxmlElementOpenの違い
実は、最初この2つの使い方が理解できなかったのですが、基本的には以下のような違いのようです
例えば、以下のようなXMLファイルがあったとします
劇団名公演名a 2018/01/01 2018/01/3 公演名b 2018/02/01 2018/02/28
この場合に、kind==xmlElementStartで得られた構成要素の名前(elementName)を抽出すると以下のように取れます
取得するソースは、以下の通り
import os, streams, parsexml, strutils if paramCount()上記のソースコードで実行結果は、以下のようになります
xml company name shows title fromdate todate title fromdate todate見ていただくと気づきますが、showは、抽出されていません。これは、showはアトリビュート「id」を保有しているためです
アトリビュートを保有する項目は、「xmlElementOpen」で分岐する必要があります
上記のコードを以下のように修正して実行します
import os, streams, parsexml, strutils if paramCount()上記のコードの実行結果は以下のとおりです
start:xml start:company start:name start:shows open:show start:title start:fromdate start:todate open:show start:title start:fromdate start:todateこの通り、この「xmlElementOpen」と「xmlElementStart」を両方キャッチしないとXMLの構成要素を全て取得することができません
要素のテキストを取得するのは、kindがCharDataであるときに取得する
上記のように、要素を特定したあとは、その要素の内容を取得します
xp.next() #xmlparserの次へノードを動かす if xp.kind==xmlCharData: #次のノードが文字列データであることを確認 value = xp.charData #文字列であれば、値に設定する else: value = ""上記のコマンドの組み合わせで、取り込めるようになりました
以上 nimでXMLファイルをパースして情報を取り込むための初歩の記事でした
PSちなみに、同様の処理をRubyとnimで実装した場合の速度比較は以下
3248のXMLファイルのパース処理
Ruby:18分4秒(4320秒)
nim :13秒
という圧倒的な差。332倍のスピード!!
ま、完全に同じ処理というわけではないのですが、それにして圧倒的です
元々Rubyを使っていた私が、処理速度の向上を目指してnimという言語を使っていろいろ試しています当たり前ですが、言語の違いによる戸惑いがあります。日本語のドキュメントもあまりないこともあり、基本中の基本も含めハマったポイント(エラーメッセージ中心に)を整理しておきますSIGSEGV: Illegal storage access.「SIGSEGV: Illegal storage access.(Attempt to read from nil?)」このエラーメッセージを見て、nil値を読み込む処理をしているつもりはなかったのですが、結果としては対象変数の初期化が必要だっただけでしたエラー...
[nim]Ruby使いがnimを使いだしてハマったポイント - 演劇とかの感想文ブログ
新しい開発言語を学ぶ必要に迫られ、今流行りの言語を色々みましたが、最終的にnimをこれから色々触ってみようという結論にいたりました。情報がまだまだ少なく、あまり有名でないこの開発言語について、少しづつ情報をためていく為の最初の一歩として「何故 nimなのか」と、開発環境の構築を記事にしておきます(2018年4月現在)処理速度の速い言語を求めて完全な日曜プログラマの私は、演劇感想文リンクの更新のためのツールをRubyで開発していますRubyは、開発者の楽しさを追った言語で、書いていて楽しいし、様々な事ができます特...
[nim]高速処理言語nimのMacOSでのセットアップと開発、テスト環境構築 - 演劇とかの感想文ブログ