コンピュータを楽しもう!!

今、自分が面白くていろいろやってみたことを書き綴りたいと思います。連絡先はtarosa.yでgmail.comです。

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系のプログラム