Xmlファイルを読んで解析する(Android)

android-xml.png

インポートするもの

import org.xmlpull.v1.XmlPullParser;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParserException;

XMLPullParser

基本的に「次の要素に行く」しかない、単純に順番に要素を回すしかないので、苦行である。
現在の深さも知ることができるけど、getChildren()みたいなものはないのかね?!

初期化

 XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);

InputStreamなどからファイル読み込み

XmlPullParser xpp = factory.newPullParser();
xpp .setInput(InputStream,"UTF-8");
//あるいは
xpp .setInput(new StringReader(String));//入力データがファイルじゃなくて既に文字列の場合はこっちが有効

関数一覧

関数名 意味
getEventType() START_TAG, END_TAG, TEXT, など現在の状態をしめす定数を返す
getName() String タグ名を返してくれる。たとえば<HTML>ならばHTMLという文字列が返ってくる
getAttributeValue(String namespace,String id) 引数に属生名を入れると、その値を返してくれる。namespaceは属性名にnamespaceがあった場合のみ指定。たとえば<tag xmln:href ..>だったらxmlnがnmespace名だ。ないやつはnullにしておく。第2引数であるidに属性名を指定する。<div class="..だったら"class"と書く
nextText() 狙ったタグが来てその中身の内容がほしい時に使う。これもインクリメントする。
next() インクリメントしたいときに使う。戻り値はTYPE
getColumnNumber() 現在読んでいる行が何文字あるのかを返す。深さの指標になるかもしれないけど、要らないよね
getDepth() ルート要素から数えてどのくらい深くなったのか返す。数値が大きいほど深い要素
nextToken() 次の要素が何のタイプか番号で返してくれる。あとえば、2ならSTART_TAGである、等
getPositionDescription() デバッグ情報的な文字列を返してくれる

TYPEの種類

定数名 getName可能か
START_DOCUMENT 0 X
END_DOCUMENT 1 X
START_TAG 2 O
END_TAG 3 O
TEXT 4 X
CDSECT 5 X
ENTITY_REF 6 O
IGNORABLE_WHITESPACE 7 X
PROCESSING_INSTRUCTION 8 X
COMMENT 9 X
DOCDECL 10 X

タグの名前を取得 getName()

もし今のタイプが START_TAG, END_TAG, or ENTITY_REFでなかったら、nullがかえってくる。

属性を取得

ループの回し方

 int eventType = xpp.getEventType();
 while (eventType != XmlPullParser.END_DOCUMENT) {
          if(eventType == XmlPullParser.START_DOCUMENT) {
              System.out.println("Start document");
          } else if(eventType == XmlPullParser.START_TAG) {
              System.out.println("Start tag "+xpp.getName());
          } else if(eventType == XmlPullParser.END_TAG) {
              System.out.println("End tag "+xpp.getName());
          } else if(eventType == XmlPullParser.TEXT) {
              System.out.println("Text "+xpp.getText());
          }
          eventType = xpp.next();//increment
         }

お目当てのタグを見つける

while (eventType != XmlPullParser.END_DOCUMENT) {
                if(eventType == XmlPullParser.START_DOCUMENT) {
                    System.out.println("Start document");
                } else if(eventType == XmlPullParser.START_TAG) {
                    if(xpp.getName().equals("library_nodes")){
                        System.out.println("お目当てのタグ発見!!"+xpp.getName());
                    }
                } 
                eventType = xpp.next();
            }

なんか、ゴリ押しな方法に思える。

お目当てのタグを見つけた後、それの子要素をすべて取得★

こういう方法もありますが

while (eventType != XmlPullParser.END_TAG || !tagname.equals("お目当てのタグ名")) {
}

whileの条件文が長ったらしい。
もっとエレガントな方法は無いかのお~??
while((eventType = xpp.next())>XmlPullParser.END_DOCUMENT){
            if(eventType == XmlPullParser.END_TAG) {
                tagname=xpp.getName();
                if(tagname.equals("お目当てのタグ名")){break;}//ループ脱出
                }

うーん。

JavaでXMLPullParserの練習

XML読む挙動をチェックするのに、いちいちAndroidに繋いでられるか!!!という人のために
Java版のXMLPullParserがあります。
もともとはこっちが本家でAndroid SDKがそれを採用したかんじ。
ダウンロードすると
kxml2-2.3.0.jarというようなファイルがダウンロードされます。

getPositionDescription

デバッグ情報的なものを返してくれる
たとえばこんなXMLファイルだった場合

<node id="Camera" name="Camera">
<lookat>
-14.931169 -43.886237 3.883330 39.934829 167.378409 37.941412 -0.038753 -0.149219 0.988044
</lookat>
<instance_camera url="#Camera-camera"/>
</node>
</visual_scene>
</library_visual_scenes>
<scene>
<instance_visual_scene url="#SketchUpScene"/>
</scene>
</COLLADA>
START_TAG <node id='Camera' name='Camera'>@4443:42 in java.io.InputStreamReader@77e1ee5d
TEXT (whitespace)@4444:13 in java.io.InputStreamReader@77e1ee5d
START_TAG <lookat>@4444:21 in java.io.InputStreamReader@77e1ee5d
TEXT 
               ...@4448:13 in java.io.InputStreamReader@77e1ee5d
END_TAG </lookat>@4448:22 in java.io.InputStreamReader@77e1ee5d
TEXT (whitespace)@4449:13 in java.io.InputStreamReader@77e1ee5d
START_TAG (empty) <instance_camera url='#Camera-camera'>@4449:52 in java.io.InputStreamReader@77e1ee5d
END_TAG </instance_camera>@4449:52 in java.io.InputStreamReader@77e1ee5d
TEXT (whitespace)@4450:10 in java.io.InputStreamReader@77e1ee5d
END_TAG </node>@4450:17 in java.io.InputStreamReader@77e1ee5d
TEXT (whitespace)@4451:7 in java.io.InputStreamReader@77e1ee5d
END_TAG </visual_scene>@4451:22 in java.io.InputStreamReader@77e1ee5d
TEXT (whitespace)@4452:4 in java.io.InputStreamReader@77e1ee5d
END_TAG </library_visual_scenes>@4452:28 in java.io.InputStreamReader@77e1ee5d
TEXT (whitespace)@4453:4 in java.io.InputStreamReader@77e1ee5d
START_TAG <scene>@4453:11 in java.io.InputStreamReader@77e1ee5d
TEXT (whitespace)@4454:7 in java.io.InputStreamReader@77e1ee5d
START_TAG (empty) <instance_visual_scene url='#SketchUpScene'>@4454:52 in java.io.InputStreamReader@77e1ee5d
END_TAG </instance_visual_scene>@4454:52 in java.io.InputStreamReader@77e1ee5d
TEXT (whitespace)@4455:4 in java.io.InputStreamReader@77e1ee5d
END_TAG </scene>@4455:12 in java.io.InputStreamReader@77e1ee5d
TEXT (whitespace)@4456:1 in java.io.InputStreamReader@77e1ee5d
END_TAG </COLLADA>@4456:11 in java.io.InputStreamReader@77e1ee5d

xml

サポートサイト Wikidot.com xml