グローバル関数 ローカル関数
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: }