/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 【機能概要】 : XML解析・データ配列化API C言語標準のlibxml2を用いてXMLの解析を行い、解析結果を配列データ として呼び元プログラムに返却する 本プログラムは、C言語(C++ではない)ため、他のAPIとは呼び方や make方法が異なることに注意する。 【作成日】 : 2021.04.23 【呼出形式】 : GG_SHM1100 ( char *filename # XMLファイル名称 ) 【戻り値】 : char* # 解析結果配列データ 【XML記述サンプル】
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ #include #include #include #include #include #include #include #include #include #define STR_NULL "" #define GG_SHM1100_MaxRow 1000 #define GG_SHM1100_MaxColumn 100 #define GG_SHM1100_MaxAttbSz 768 #define GG_SHM1100_MaxRetSz 1024000 iconv_t cd; static char ***dataStruct ; /* XML分析結果の一時保存領域 */ static char *c_data ; /* 上位APへのデータ返却領域 */ static int row = 0 ; static int column = 0 ; static int errorflg = 0 ; /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 三次元配列データの作成(テーブルデータの一時保存用に使用) _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ char*** GG_SHM1100_malloc( int rows , int cols , int colsize ) { char ***a, **b, *c; int i = rows; int j = cols; int t = sizeof(char) * colsize; a = (char***)malloc((sizeof(*a) + sizeof(**a) * j + t * j) * i); if(a == NULL){ return a; } if(a != NULL){ b = (char**)(a + i); c = (char*)(b + i * j); for(int idx1 = 0; idx1 < i; idx1++){ a[idx1] = b; for(int idx2 = 0; idx2 < j; idx2++){ b[idx2] = c; c += t; } b += j; } } return a; } /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 文字コード変換処理(今後の拡張用) _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ int SHM1100_iconv (char *fptr , size_t fsize , char *tptr , size_t tsize) { char *fwork , *twork ; size_t fsz , tsz , ret ; fwork = fptr ; twork = tptr ; fsz = fsize ; tsz = tsize ; ret = iconv(cd, &fwork, &fsz, &twork, &tsz); if (ret == (size_t)-1) { printf ( "errno=%d\n",errno) ; return (-1) ; } *twork = '\0' ; return (0) ; } /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ XMLデータ分析処理メイン _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ static void start_element_ns_callback(void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes) { char *fptr ; char toLocalname[256] , toAtts[768] , toParm[1024] ; #ifdef _DBG_SHM1100 fprintf(stdout, "nb_namespaces=[%d] nb_attributes=[%d] nb_defaulted=[%d]\n" ,nb_namespaces,nb_attributes,nb_defaulted) ; #endif if ( errorflg < 0 ) return ; /* タグ名称(localname)処理 */ if ( localname != NULL ) { errorflg = SHM1100_iconv ( (char *)localname , strlen( (const char *)localname ) , toLocalname , sizeof( toLocalname ) - 1 ); if (errorflg == -1) return ; #ifdef _DBG_SHM1100 fprintf(stdout, "localname = <%s>\n", toLocalname); #endif } #ifdef _DBG_SHM1100 printf("nb_attributes=[%d]\n",nb_attributes) ; #endif /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Sentenceタグ対応(where句) where句を複数行に分割記述する場合、Partタグを用いる。その場合は Sentenceタグには何も書かないため、下記のロジックになる ※ XML記述サンプル参照(上記) _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ if ( strcmp ( toLocalname , "Sentence" ) == 0 && nb_attributes == 0 ) { column = 2 ; strcpy ( dataStruct[row][column] , STR_NULL ) ; strcpy ( dataStruct[row][column+1] , STR_NULL ) ; } /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ xml / attributes 処理 例: という記述は、 ・toLocalname に 「Table」 ・attributes[n] に 「id」 (nは5の倍数) ・attributes[n+3] に 「M_TEST01」 が格納される _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ for(int i = 0 ; i < nb_attributes ; i++ ) { if ( attributes[i*5] == NULL ) continue ; /* attributes名称(id等)の取得 */ errorflg = SHM1100_iconv ( (char *)attributes[i*5] , strlen( (const char *)attributes[i*5] ) , toAtts , sizeof( toAtts ) - 1 ); if (errorflg == -1) return ; #ifdef _DBG_SHM1100 fprintf(stdout, "Atts[%d] = <%s> " , i , toAtts) ; #endif /* attributes値(M_TEST01等)の取得 */ fptr = (char *)attributes[i*5+3] ; strtok ( fptr , "\"" ) ; errorflg = SHM1100_iconv ( fptr , strlen( (const char *)fptr ) , toParm , sizeof( toParm ) - 1 ); if (errorflg == -1) return ; #ifdef _DBG_SHM1100 fprintf(stdout, "Parm[%d] = <%s>\n" , i , toParm) ; #endif /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 各タグ/アトリビュート/値の処理 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ /* Table タグ処理 */ if ( strcmp ( toLocalname , "Table" ) == 0 ) { if ( strcmp ( toAtts , "id" ) == 0 ) { row = 0 ; column = 0 ; strcpy ( dataStruct[row][column] , toParm ) ; strcpy ( dataStruct[row+1][column] , STR_NULL ) ; #ifdef _DBG_SHM1100 printf("dataStruct[%d][%d]=[%s]\n",row,column,dataStruct[row][column]) ; #endif } else if ( strcmp ( toAtts , "name" ) == 0 ) { /* テーブル名に対する日本語を記述するが、システムでは未使用 */ } else { printf ( "Tableタグに (id or name)以外のタグを検出\n" ) ; errorflg = -3 ; } /* Search タグ処理 */ } else if ( strcmp ( toLocalname , "Search" ) == 0 ) { if ( strcmp ( toAtts , "id" ) == 0 ) { if ( row != 0 || column != 0 ) { row ++ ; strcpy ( dataStruct[row][0] , dataStruct[0][0] ) ; strcpy ( dataStruct[row+1][0] , STR_NULL ) ; } column = 1 ; strcpy ( dataStruct[row][column] , toParm ) ; #ifdef _DBG_SHM1100 printf("dataStruct[%d][%d]=[%s]\n",row,column,dataStruct[row][column]) ; #endif } else { printf ( "Searchタグに id 以外のタグを検出\n" ) ; errorflg = -4 ; } /* Sentence タグ処理 */ } else if ( strcmp ( toLocalname , "Sentence" ) == 0 ) { if ( strcmp ( toAtts , "where" ) == 0 ) { column = 2 ; strcpy ( dataStruct[row][column] , toParm ) ; strcpy ( dataStruct[row][column+1] , STR_NULL ) ; #ifdef _DBG_SHM1100 printf("dataStruct[%d][%d]=[%s]\n",row,column,dataStruct[row][column]) ; #endif } else { printf ( "Sentenceタグに where 以外のタグを検出\n" ) ; errorflg = -5 ; } /* iData タグ処理 */ } else if ( strcmp ( toLocalname , "iData" ) == 0 ) { if ( strcmp ( toAtts , "column" ) == 0 ) { column ++ ; strcpy ( dataStruct[row][column] , toParm ) ; strcpy ( dataStruct[row][column+1] , STR_NULL ) ; #ifdef _DBG_SHM1100 printf("dataStruct[%d][%d]=[%s]\n",row,column,dataStruct[row][column]) ; #endif } else { printf ( "iDataタグに column 以外のタグを検出\n" ) ; errorflg = -6 ; } /* Part タグ処理 (Sentence タグの複数行対応用)*/ } else if ( strcmp ( toLocalname , "Part" ) == 0 ) { if ( strcmp ( toAtts , "where" ) == 0 ) { column = 2 ; if ( strlen ( dataStruct[row][column] ) > 0 ) { strcat ( dataStruct[row][column] , " " ) ; } strcat ( dataStruct[row][column] , toParm ) ; #ifdef _DBG_SHM1100 printf("dataStruct[%d][%d]=[%s]\n",row,column,dataStruct[row][column]) ; #endif } else { printf ( "Partタグに where 以外のタグを検出\n" ) ; errorflg = -7 ; } } } } /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ XMLファイル・オープン/読込み処理 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ static int read_callback(void *context, char *buffer, int len) { FILE *fp = (FILE *) context; #ifdef _DBG_SHM1100 fprintf(stderr, "*** read_callback()\n"); #endif return fread(buffer, 1, len, fp); } /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ XMLファイル・クローズ処理 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ static int close_callback(void *context) { FILE *fp = (FILE *) context; #ifdef _DBG_SHM1100 fprintf(stderr, "*** close_callback()\n"); #endif return fclose(fp); } /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 共有メモリアクセス定義情報解析処理 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ char* GG_SHM1100 ( char *filename ) { xmlParserCtxtPtr xmlctx; xmlSAXHandler saxh; FILE *fp; struct stat stat_buf ; char *FileChar ; int rc ; int i , dquot ; errorflg = 0 ; /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ XMLファイルの文字コード変換オープン処理 ※ encoding値によってコード変換されるため、本処理は今後の拡張用 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ #ifdef _SJIS_SHM1100 cd = iconv_open("UTF-8" , "SHIFT-JIS") ; #else cd = iconv_open("UTF-8" , "UTF-8") ; #endif if (cd == (iconv_t)-1) { fprintf(stderr,"iconv_open(%s) failed\\n", "UTF-8"); errorflg = -11 ; return (char*)NULL ; } /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ XMLファイルの存在有無チェック _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ if ( stat ( filename, &stat_buf ) != 0 ) { printf ( "xmlファイルがありません\n" ) ; errorflg = -8 ; return (char*)NULL ; } /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ XML要素の最大値チェック dataStruct の要素サイズは、GG_SHM1100_MaxAttbSz まで _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ fp = fopen(filename, "r"); FileChar = (char *)malloc ( stat_buf.st_size + 1 ) ; fread ( FileChar , 1 , stat_buf.st_size , fp ) ; fclose ( fp ) ; FileChar [ stat_buf.st_size ] = '\0' ; dquot = -1 ; i = 0 ; for ( i=0 ; i < stat_buf.st_size ; i++ ) { if ( FileChar[i] == '\"' ) { if ( dquot == -1 ) { dquot = 0 ; } else { if ( dquot > GG_SHM1100_MaxAttbSz ) { printf ( "xmlファイルの要素が%dバイトを越えています\n",GG_SHM1100_MaxAttbSz ) ; errorflg = -9 ; return (char*)NULL ; } dquot = -1 ; } } else { if ( dquot != -1 ) { dquot ++ ; } } } free ( (void *)FileChar ) ; /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ XMLデータの分析結果一時保存領域の確保 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ dataStruct = GG_SHM1100_malloc ( GG_SHM1100_MaxRow + 1 , GG_SHM1100_MaxColumn + 1 , GG_SHM1100_MaxAttbSz + 1 ) ; /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 上位APへの分析結果返却領域 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ c_data = (char *) malloc ( GG_SHM1100_MaxRetSz + 1 ) ; /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ libxml2の利用手続き部 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ xmlInitParser(); xmlDefaultSAXHandlerInit(); xmlSAX2InitDefaultSAXHandler(&saxh, 1); xmlSAXVersion(&saxh, 2); saxh.startElementNs = start_element_ns_callback; /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ XMLファイルのParser登録 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ fp = fopen(filename, "r"); xmlctx = xmlCreateIOParserCtxt(&saxh, NULL, read_callback, close_callback, fp, XML_CHAR_ENCODING_NONE); /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ パース開始 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ if (xmlParseDocument(xmlctx)) { xmlParserError(xmlctx, "xmlParseDocument"); errorflg = -12 ; printf ( "xmlファイル解析エラー\n" ) ; free ( (void *)dataStruct ) ; return (char*)NULL ; } /* 不要の可能性あり */ xmlClearParserCtxt(xmlctx); /* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 上位APへの返却(c_data)用に編集 [データ01]\t[データ02]\t[データ03]\t・・・\n [データ11]\t[データ12]\t[データ13]\t・・・\n ※ 上記の繰り返し _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */ i = 0 ; for ( row=0 ; strcmp(dataStruct[row][0],STR_NULL)!=0 ; row++ ){ for ( column=0 ; strcmp(dataStruct[row][column],STR_NULL)!=0 ; column++ ){ #ifdef _DBG_SHM1100 printf("dataStruct[%d][%d]=[%s]\n",row,column,dataStruct[row][column]) ; #endif strcpy ( c_data + i ,dataStruct[row][column] ) ; i = i + strlen(dataStruct[row][column]) ; c_data [ i ] = '\t' ; i ++ ; } if ( column != 0 ) { c_data [ i ] = '\n' ; i ++ ; } if ( i > GG_SHM1100_MaxRetSz ) { errorflg = -13 ; printf ( "分析結果サイズオーバーエラー[%d バイト]\n" , GG_SHM1100_MaxRetSz ) ; free ( (void *)dataStruct ) ; return (char*)NULL ; } } c_data[i] = '\0' ; free ( (void *)dataStruct ) ; if ( errorflg == 0 && strlen(c_data) < 1 ) { printf ( "xmlファイルの中がありません\n" ) ; errorflg = -10 ; } if ( errorflg != 0 ) { printf ( "errorflg=%d\n",errorflg ) ; return (char*)NULL ; } return c_data ; }