DSでXML形式のデータを読む
DSでかな漢字変換を行うために、Yahoo!JAPANテキスト解析 Web APIを使おうという話を書いたのですが、APIが返してくるデータはXML形式のデータです。
XML形式のデータを解析できないと「かな漢字変換処理」がうまく行かないので、簡単なXML解析プログラムを作ってみました。
XML解析に必要なこと
自分なりに、XML形式のデータを解析するために、何が欲しいかを考えてみました。下記します。
- タグの指定とその内容の取得
- タグの指定とそのタグに設定された要素の取得
- 任意の要素文字の括りコード対応
- タグは階層構造を持つので、階層構造への対応
- 同階層ある同名タグを順番に取得できる
- コメントの無視
- &で始まるの特殊文字への対応
これらに対応できるように、XMLを解析する関数を作ってみました。
最初のタグ開始位置までスキップ bool xmlTagTopFound( FILE *fp, char kigou );
kigou文字が出てくるまで読み飛ばします。見つからなければFalseを返します。
例、xmlTagTopFound( fp, '<' ); //最初のタグ開始位置までスキップ
タグを探します int xmlSearchTag( FILE *fp, char* tag, int n );
指定されたファイルから、n個目の指定したタグを探しファイルポインタをそこまで進めます。n個目を探すことになるので、タグの階層指定はできません。
タグを探します(階層指定可) int xmlSearchLayerTag( FILE *fp, char* tagPath, long readPosition );
ファイルの指定位置以降にあるタグを探します。タグは"ffff/oooo/abc"と階層指定も可能です。
タグ名を取得します int xmlReadTag( FILE *fp, char *tagName );
ファイルの指定位置以降で最初にあるタグ名を取得します。
タグの内容を取得します int xmlGetValue( FILE *fp, char* tagPath, char* value, int length, long readPosition );
ファイルの指定位置以降にあるタグの内容を取得します。タグは"ffff/oooo/abc"と階層指定も可能です。
これらを使って、タグを読むテストプログラムを作りました。下記です。前回のプログの漢字変換候補を読み出します。
//************************************************** // タグの内容取得テスト //************************************************** void xmlTagReadTest( FILE *fp ) { int ret; long posSegmentList; char tmp[256]; char tagData[256]; int i, j; long posSegment; fseek( fp, 0, SEEK_SET ); //ファイルの先頭に xmlTagTopFound( fp, '<' ); //最初のタグ開始位置までスキップ //"ResultSet/Result/SegmentList"タグを探す xmlSearchLayerTag( fp, "ResultSet/Result/SegmentList", ftell(fp) ); posSegmentList = ftell( fp ); //SegmentList開始位置退避 for( i=0; i<128; i++ ){ fseek( fp, posSegmentList, SEEK_SET ); //SegmentList開始位置に復帰させる ret = xmlSearchTag( fp, "Segment", i+1 ); //(i+1)個目の"Segment"タグを探してその位置に移動する if( ret!=XML_TRUE ){ break; } posSegment = ftell( fp ); //探した"Segment"タグ位置を退避 //"Segment"タグの中にある"SegmentText"の内容を tagData に取得する xmlGetValue( fp, (char*)"SegmentText", tagData, 256, posSegment ); strcpy( tmp, "「" ); strcat( tmp, tagData ); strcat( tmp, "」" ); ShinoUpPrint( SubScreenA, (u8 *)tmp, RGB(31,31,31), RGB( 0,0,0 ), 1, RGB( 0,0,0 ) ); fseek( fp, posSegment, SEEK_SET ); //(i+1)個目の"Segment"位置に復帰 //"Segment"タグの中にある"CandidateList"タグを探す xmlSearchTag( fp, "CandidateList", 1 ); strcpy( tmp, "候補: " ); for( j=0; j<128; j++ ){ //"CandidateList"タグ中にある"Candidate"の内容を tagData に取得する ret = xmlGetValue( fp, (char*)"Candidate", tagData, 256, ftell(fp) ); if( ret!=XML_TRUE ){ break; } strcat( tmp, tagData ); strcat( tmp, "/" ); } ShinoUpPrintBox( SubScreenA, (u8 *)tmp, 42, RGB(31,31,31), RGB( 0,0,0 ), 1, RGB( 0,0,0 ) ); ShinoScrnUp( SubScreenA, RGB( 0,0,0 ) ); } }
次に、要素の解析プログラムです。
要素名を読み込みます int xmlReadElement( FILE *fp, char* elemName );
タグ名を探した後、そのタグに含まれる要素名を取得します。
要素の括りコードの取得 int xmlPassElmSpc( FILE *fp );
要素内容の括りコードを取得します。ただし、コードはダブルコーテーション(0x22)かシングルコーテーション(0x27)のどちらか限定です。
chrdatで括られた内容をスキップします int xmlPassElmValue( FILE *fp, u8 chrdat );
chrdatで括られた内容を読み飛ばします。読み込む必要がないとき読み飛ばすことができます。
chrdatで括られた内容を取得します int xmlGetElmValue( FILE *fp, u8 chrdat, char *value );
codeで括られた内容を取得します。
タグの要素を無視する int xmlPassElem( FILE *fp );
タグの要素を無視し、全てスキップします。
これらを使って、要素を読むテストプログラムを作りました。下記です。
//************************************************** // タグの要素取得テスト //************************************************** void xmlElementReadTest( FILE *fp ) { int ret, code; char tmp[256]; char elementData[256]; fseek( fp, 0, SEEK_SET ); xmlTagTopFound( fp, '<' ); //最初のタグ開始位置までスキップ xmlSearchTag( fp, "ResultSet", 1 ); //1つ目の"ResultSet"タグを探す while( true ){ ret = xmlReadElement( fp, elementData ); //要素名を読み込む if( ret!=XML_TRUE ){ break; } //要素が無ければ終了 code = xmlPassElmSpc( fp ); //要素内容の括りコードの取得 if( mojiHikaku( elementData, "xmlns", 0 )==true ){ //要素名がxmlnsの場合はスキップする strcpy( tmp, "要素名「" ); strcat( tmp, elementData ); strcat( tmp, "」はスキップします" ); xmlPassElmValue( fp, code ); //codeで括られた内容をスキップする } else{ strcpy( tmp, "要素名「" ); strcat( tmp, elementData ); strcat( tmp, "」の内容は、「" ); xmlGetElmValue( fp, code, elementData ); //codeで括られたデータ内容をelementDataに読み出す strcat( tmp, elementData ); strcat( tmp, "」" ); } ShinoUpPrintBox( MainScreenA, (u8 *)tmp, 42, RGB(31,31,31), RGB( 0,0,0 ), 1, RGB( 0,0,0 ) ); ShinoScrnUp( MainScreenA, RGB( 0,0,0 ) ); } }
とりあえず、これでYahoo!JAPANテキスト解析 Web APIから戻ってくるデータを解析することができるようになりました。テストサンプルはNDS Program Roomにアップしたいと思います。
後は、このデータがUTF-8なので、これの読み込みプログラムを作らなければなりません。
本当にやりたいことリスト
(ブログの終わりにやりたいことを書いておきたいと思います)
- 求職活動・・・このブログで興味を持った人一声かけてください。m(_ _)m
- Androidプログラム
- Web系のプログラム