/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
【機能概要】 : 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 ;
}