MUSASHI C source: mssXtTag.c


グローバル関数
mssGetNullTag mssGetTag mssGetTagAtt mssGetTagCont mssReadSetTop mssReadTag mssSkipToBody


ローカル関数
mkStr


0001: /** 
0002:  * # CHAPTER # 
0003:  * ============================================================================ 
0004:  * MUSASHIで用いられるXMLtableのタグを操作する関連の関数 
0005:  * ============================================================================ 
0006:  * 通常の流れ 
0007:  * 1. mssReadTagでファイルから読み込み特定のタグをStringsにセットする 
0008:  * 2. mssGetTagで必要なタグをStringsにセットする 
0009:  * 3. mssGetTagCont,mssGetTagAtt,mssGetNulTagなどで内容を取り出す 
0010:  * 4. 2で確保したStringsを開放する 
0011:  * 5. 2,3,4の処理を繰り返す 
0012:  * 6. 1で確保したStringsを開放する 
0013:  * 
0014:  * mssGetTagCont,mssGetTagAtt,mssGetNulTagはStringsの文字列単にを検索し、最初に  
0015:  * みつけた内容を返すので、Stringsの中にタグが複数ある場合はmssGetTagで 
0016:  * あらかじめ必要なタグをStringsにセットしておく 
0017:  */ 
0018:  
0019: #include <mssInput.h
0020: #include <stdio.h> 
0021: #include <stdlib.h> 
0022: #include <string.h> 
0023:  
0024: /* ############ グローバル変数 ##############*/ 
0025: extern struct mssGlobalVariables mssGV; 
0026:  
0027:  
0028: /**  
0029:  * # FUNCTION #  
0030:  * 3つ以内の文字列から新しい一つの文字列を作成し、そのポインタを返す。 
0031:  * その際、新たな文字列領域が確保される。 
0032:  * Tagの作成などに利用 
0033:  * ex.) bgn="<", str="field", end=">" 
0034:  *      -> 
0035:  *      "<field>" 
0036:  */      
0037: static char *mkStr(char *bgn, char *str, char *end){ 
0038:   char *tag; 
0039:    
0040:   tag=mssMalloc(sizeof(char)*(strlen(bgn)+strlen(str)+strlen(end)+1),"mkStr"); 
0041:   strcpy(tag,bgn); 
0042:   strcat(tag,str); 
0043:   strcat(tag,end); 
0044:   return(tag); 
0045: } 
0046:  
0047: /**  
0048:  * # FUNCTION #  
0049:  * ファイル(fp)から指定タグ(tag)を検索しStringsにセットし、そのポインタを返す。 
0050:  * 開始タグが無ければNULLを返す。 
0051:  * 開始タグがあり、終了タグが無ければエラー表示&終了。 
0052:  * ex.) 
0053:  * ファイルが"<xmltable><header>....</header></xmltable>"とすると、 
0054:  * 返値strings->str="<header><title>this is title</title></header>" 
0055:  */ 
0056: struct mssStrings *mssReadTag(char *tag, struct mssFPR *fp){ 
0057:      
0058:   struct mssRec *rec; 
0059:   int   len; 
0060:   char *bgnTag; 
0061:   char *endTag; 
0062:   char *tagTmp=NULL; 
0063:   struct mssStrings *strings=NULL; 
0064:  
0065:   rec=mssInitRec(); 
0066:  
0067:   /*beginタグとendタグをそれぞれセットする*/ 
0068:   bgnTag=mkStr("<" ,tag,"" ); 
0069:   endTag=mkStr("</",tag,">"); 
0070:  
0071:   /*beginタグの検索*/ 
0072:   while( EOF != (len=mssReadRec(fp, rec)) ){ 
0073:     if( NULL != (tagTmp=strstr(rec->pnt, bgnTag)) ){ 
0074:       strings=mssInitStrings(); 
0075:       mssCatStrings(strings, tagTmp); 
0076:       mssCatStrings(strings, "\n"); 
0077:       break; 
0078:     } 
0079:   } 
0080:  
0081:   /*beginタグがなかった*/ 
0082:   if(len==EOF) return(NULL); 
0083:    
0084:   /*endタグの検索*/ 
0085:   while( EOF != (len=mssReadRec(fp, rec)) ){ 
0086:     if( NULL != (tagTmp=strstr(rec->pnt, endTag)) ){ 
0087:       mssCatnStrings(strings, rec->pnt, rec->pnt-tagTmp+strlen(endTag)); 
0088:       mssCatStrings(strings, "\n"); 
0089:       break; 
0090:     }else{ 
0091:       mssCatStrings(strings, rec->pnt); 
0092:       mssCatStrings(strings, "\n"); 
0093:     } 
0094:   } 
0095:  
0096:   /*endタグがなかった*/ 
0097:   if(len==EOF){ 
0098:     mssShowErrMsg("there is not the end tag : %s",tag); 
0099:     mssEnd(mssErrorNoDefault); 
0100:   } 
0101:  
0102:   mssFreeRec(rec); 
0103:   mssFree(bgnTag); mssFree(endTag); 
0104:  
0105:   return(strings); 
0106: } 
0107:  
0108: /**  
0109:  * # FUNCTION # 
0110:  * 文字列(str)から指定タグ(tag)で囲まれた文字列をStringsにセットし、 
0111:  * そのポインタを返す。 
0112:  * 開始タグが無ければNULLを返す。 
0113:  * 開始タグがあり、終了タグが無ければエラー表示&終了。 
0114:  * さらに*posに、検索された開始タグの先頭のポインタをセットする。 
0115:  * タグの階層は考慮していないので、同名タグが入れ子構造になっている場合は 
0116:  * うまく動作しない。 
0117:  * ex.) 
0118:  * *str="<header><title>this is title</title><header>"とすると、 
0119:  * 返値strings->str="<title>this is title</title>" 
0120:  * *posは、オリジナルの*strの"<title>...."の先頭位置がセットされる。 
0121:  */ 
0122: struct mssStrings *mssGetTag(char *tag, char *str, char **pos){ 
0123:  
0124:   char *bgnTag; 
0125:   char *endTag; 
0126:   char *bgnTagTmp; 
0127:   char *endTagTmp; 
0128:   struct mssStrings *strings; 
0129:  
0130:   /*beginタグとendタグをそれぞれセットする*/ 
0131:   bgnTag=mkStr("<" ,tag,"" ); 
0132:   endTag=mkStr("</",tag,">"); 
0133:  
0134:   /*beginタグの検索*/ 
0135:   bgnTagTmp=strstr(str, bgnTag); 
0136:   if( bgnTagTmp == NULL ){ 
0137:     return(NULL); 
0138:   } 
0139:  
0140:   /*endタグの検索*/ 
0141:   endTagTmp=strstr(bgnTagTmp, endTag); 
0142:   if( endTagTmp == NULL ){ 
0143:     mssShowErrMsg("there is not the end tag : %s",tag); 
0144:     mssEnd(mssErrorNoDefault); 
0145:   } 
0146:  
0147:   strings=mssInitStrings(); 
0148:   mssCatnStrings(strings, bgnTagTmp, endTagTmp-bgnTagTmp+strlen(endTag)); 
0149:  
0150:   mssFree(bgnTag); mssFree(endTag); 
0151:  
0152:   *pos=bgnTagTmp; 
0153:   return(strings); 
0154: } 
0155:  
0156: /**  
0157:  * # FUNCTION # 
0158:  * 文字列(str)から空要素タグを検索し、あれば1、なければ0を返す。 
0159:  * 空要素タグの例: <numeric/> 
0160:  */ 
0161: int mssGetNullTag(char *str, char *tag){ 
0162:  
0163:   char *t; 
0164:   int   ret=0; 
0165:  
0166:   /*タグを作る*/ 
0167:   t=mkStr("<",tag,"/>"); 
0168:  
0169:   /*タグの検索*/ 
0170:   if(NULL != strstr(str, t)) ret=1; 
0171:  
0172:   mssFree(t); 
0173:   return(ret); 
0174: } 
0175:  
0176: /**  
0177:  * # FUNCTION # 
0178:  * 文字列(str)から指定タグ(tag)の内容を返す。 
0179:  * 指定タグがなければNULL値を返す。 
0180:  * 開始タグがあり、終了タグが無ければエラー表示&終了。 
0181:  * strの内容は変えずに、新たにメモリを確保して、そのアドレスを返す。 
0182:  * retIgnoreが1ならば改行を無視する。 
0183:  * タグの階層は考慮していないので、同名タグが入れ子構造になっている場合は 
0184:  * うまく動作しない。 
0185:  * ex.) 
0186:  * str="<title>this is title</title>" 
0187:  * tag="title" 
0188:  * 返値="this is title" 
0189:  */ 
0190: char *mssGetTagCont(char *str, char *tag, int retIgnore){ 
0191:  
0192:   char *bgnTag; 
0193:   char *endTag; 
0194:   char *bgnTagTmp=NULL; 
0195:   char *endTagTmp=NULL; 
0196:   char *retStr=NULL; 
0197:   char *retPnt; 
0198:   char *conPnt; 
0199:   char  tmp; 
0200:  
0201:   if( str == NULL ) return(NULL); 
0202:  
0203:   /*beginタグとendタグをそれぞれセットする*/ 
0204:   bgnTag=mkStr("<" ,tag,"" ); 
0205:   endTag=mkStr("</",tag,">"); 
0206:  
0207:   /*begin,endタグの検索*/ 
0208:   bgnTagTmp=strstr(str, bgnTag); 
0209:   if( bgnTagTmp == NULL ){ 
0210:     return(NULL); 
0211:   } 
0212:  
0213:   endTagTmp=strstr(bgnTagTmp, endTag); 
0214:   if( endTagTmp == NULL ){ 
0215:     mssShowErrMsg("there is not the end tag : %s",tag); 
0216:     mssEnd(mssErrorNoDefault); 
0217:   } 
0218:  
0219:   while(*bgnTagTmp != '>') bgnTagTmp++; 
0220:   bgnTagTmp++; 
0221:  
0222:   tmp=*endTagTmp; 
0223:   *endTagTmp='\0'; 
0224:   if(retIgnore){ 
0225:     retStr=mssMalloc(sizeof(char)*(strlen(bgnTagTmp)+1),"getTagCont"); 
0226:     conPnt=bgnTagTmp; 
0227:     retPnt=retStr; 
0228:     while(conPnt!=endTagTmp){ 
0229:       if(*conPnt!='\n'){ 
0230:         *retPnt=*conPnt; 
0231:         retPnt++; 
0232:       } 
0233:       conPnt++; 
0234:     } 
0235:     *retPnt='\0';  
0236:   }else{ 
0237:     retStr=mssStrdup(bgnTagTmp); 
0238:   } 
0239:   *endTagTmp=tmp; 
0240:  
0241:   mssFree(bgnTag); mssFree(endTag); 
0242:   return(retStr); 
0243: } 
0244:  
0245: /**  
0246:  * # FUNCTION # 
0247:  * 文字列(str)から指定タグ(tag)の指定の属性(att)の値を返す。 
0248:  * 開始タグがあり、終了タグが無ければエラー表示&終了。 
0249:  * strの内容は変えずに、新たにメモリを確保して、そのアドレスを返す。 
0250:  * 属性値は'"'で囲まれていることを前提。 
0251:  * ex.) 
0252:  * str="<field no="1">...</field>" 
0253:  * 返値="1" 
0254:  */ 
0255: char *mssGetTagAtt(char *str, char *tag, char *att){ 
0256:  
0257:   char *bgnTag; 
0258:   char *bgnTagTmp; 
0259:   char *attStr; 
0260:   char *retStr=NULL; 
0261:   char *pos; 
0262:   char buf[256]; 
0263:   int i; 
0264:  
0265:   /*beginタグ、属性名をセットする*/ 
0266:   bgnTag=mkStr("<",tag," " ); 
0267:   attStr=mkStr("" ,att,"="); 
0268:  
0269:   /*beginタグの検索*/ 
0270:   bgnTagTmp=strstr(str, bgnTag); 
0271:   if( bgnTagTmp == NULL ){ 
0272:     return(NULL); 
0273:   } 
0274:  
0275:   /*一時的に">"を'\0'にする。*/ 
0276:   pos=bgnTagTmp; 
0277:   while(*pos!='>' && *pos!='\0') pos++; 
0278:   if(*pos!='>'){ 
0279:     mssShowErrMsg("not a complete tag : %s",tag); 
0280:     mssEnd(mssErrorNoDefault); 
0281:   } 
0282:   *pos='\0'; 
0283:  
0284:   /*属性の検索*/ 
0285:   bgnTagTmp=strstr(bgnTagTmp, attStr); 
0286:   if( bgnTagTmp == NULL ){ 
0287:     retStr=NULL; 
0288:   }else{ 
0289:  
0290:     /*属性値のセット*/ 
0291:     while(*bgnTagTmp!='"' && *bgnTagTmp!='\0') bgnTagTmp++; 
0292:     if(*bgnTagTmp=='\0'){ 
0293:       mssShowErrMsg("invalid attribute value : %s",att); 
0294:       mssEnd(mssErrorNoDefault); 
0295:     } 
0296:     bgnTagTmp++; 
0297:     for(i=0; *bgnTagTmp!='"' && *bgnTagTmp!='\0' && i<255; i++){ 
0298:       buf[i]=*bgnTagTmp++; 
0299:     } 
0300:     if(*bgnTagTmp=='\0' || i>=255){ 
0301:       mssShowErrMsg("invalid attribute value : %s",att); 
0302:       mssEnd(mssErrorNoDefault); 
0303:     } 
0304:     buf[i]='\0'; 
0305:     retStr=mssStrdup(buf); 
0306:   } 
0307:  
0308:   *pos='>'; 
0309:  
0310:   mssFree(bgnTag); mssFree(attStr); 
0311:   return(retStr); 
0312: } 
0313:  
0314: /**  
0315:  * # FUNCTION # 
0316:  * トップ行(xml宣言、<xmltbl>タグ)の読み込み 
0317:  * 1行目はXML宣言とみなす。 
0318:  * xmltblタグが出現するまでデータをスキップする。 
0319:  * XMLバージョン、エンコーディングをセット。 
0320:  * xmlTableのバージョンをセット。 
0321:  */ 
0322: void mssReadSetTop(struct mssHeader *header, struct mssFPR *fp){ 
0323:   struct mssRec *rec; 
0324:   struct mssStrings *buf; 
0325:   int   len; 
0326:   char  *version; 
0327:   char  *pnt; 
0328:  
0329:   rec=mssInitRec(); 
0330:   buf=mssInitStrings(); 
0331:  
0332:   len=mssReadRec(fp, rec); 
0333:   /*mssReadRecでEOFということはデータなしということ*/ 
0334:   if(len==EOF) { 
0335:     mssShowErrMsg("no input data"); 
0336:     exit(mssErrorNoDefault); 
0337:   } 
0338:  
0339:   if( 0!=strncmp(rec->pnt,"<?xml",5) ){ 
0340:     mssShowErrMsg("not XML data"); 
0341:     mssEnd(mssErrorNoDefault); 
0342:   }else{ 
0343:     header->xmlver=mssGetTagAtt(rec->pnt, "?xml", "version"); 
0344:     header->xmlenc=mssGetTagAtt(rec->pnt, "?xml", "encoding"); 
0345:     len=mssReadRec(fp, rec); 
0346:     /*mssReadRecでEOFということはデータなしということ*/ 
0347:     if(len==EOF) { 
0348:       mssShowErrMsg("no input data"); 
0349:       exit(mssErrorNoDefault); 
0350:     } 
0351:   } 
0352:  
0353:   /*xmltblタグが見つかるまで読み続ける*/ 
0354:   while(1) { 
0355:     pnt=strstr(rec->pnt,"<xmltbl"); 
0356:     if(pnt!=NULL)break; 
0357:     len=mssReadRec(fp, rec); 
0358:     if(len==EOF) { 
0359:       mssShowErrMsg("cannot find xmltbl tag"); 
0360:       exit(mssErrorNoDefault); 
0361:     } 
0362:   } 
0363:  
0364:   mssCatStrings(buf, pnt); 
0365:  
0366:   version = mssGetTagAtt(buf->str, "xmltbl", "version"); 
0367:   if(version!=NULL){ 
0368:     header->version = (int)(atof(version)*10); 
0369:   }else{ 
0370:     mssShowErrMsg("version of XMLtable is not specified"); 
0371:     exit(mssErrorNoDefault); 
0372:   } 
0373:  
0374:   mssFreeRec(rec); 
0375:   mssFreeStrings(buf);  /*20021126追加*/ 
0376: } 
0377:  
0378: /**  
0379:  * # FUNCTION # 
0380:  * データ部までスキップする。 
0381:  * 具体的には"<body><![CDATA["の次の行にファイルポインタを移す 
0382:  * <body>タグは一行に書かれていることが前提 
0383:  */ 
0384: void mssSkipToBody(struct mssFPR *fp){ 
0385:   struct mssRec *rec=NULL; 
0386:  
0387:   if(mssGV.txtFlg) return; 
0388:  
0389:   rec=mssInitRec(); 
0390:  
0391:   while(EOF!=mssReadRec(fp, rec)){ 
0392:     if( 0==strncmp(rec->pnt,MssBeginBodyString,15) ){ 
0393:       mssFreeRec(rec); 
0394:       return; 
0395:     } 
0396:   } 
0397:   mssFreeRec(rec); 
0398:   mssShowErrMsg("can't find the end body tag"); 
0399:   exit(mssErrorNoDefault); 
0400: }