MUSASHI C source: xmltagcnt.c


0001: /*============================================================================*/ 
0002: /* 変更履歴                                                                   */ 
0003: /*----------------------------------------------------------------------------*/ 
0004: /* 1.0 : 新しいAPIに対応                                                      */ 
0005: /*============================================================================*/ 
0006:  
0007: #include <musashi.h
0008: #include <stdio.h> 
0009: #include <stdlib.h> 
0010: #include <string.h> 
0011: #include <libxml/parser.h> 
0012: #include <libxml/parserInternals.h> 
0013: #include <libxml/encoding.h> 
0014: #include <iconv.h> 
0015: #include <errno.h> 
0016: #include <glob.h> 
0017: #include <stdarg.h> 
0018:  
0019: #include <xmltagcntHelp.h> 
0020: struct mssComHelp comHelp={ 
0021:   "xmltagcnt",    /* コマンド名       */                                       
0022:   "1.0",          /* バージョン       */ 
0023:   HELPT,          /* コマンドタイトル */ 
0024:   HELPS,          /* 要約             */                                     
0025:   HELPE,          /* 利用例           */ 
0026:   HELPR,          /* 参照コマンド     */ 
0027:   HELPA,          /* 作者情報         */                                     
0028:   HELPB,          /* バグレポート情報 */ 
0029:   HELPH           /* ホームページ     */ 
0030: };           
0031:  
0032: #define UNDEF 0 
0033: #define MAX_NEST 32 
0034: #define LOCAL_BUF 256 
0035: #define EncMax MssFieldMaxLen  /*iconvで使う出力用文字列長*/ 
0036:  
0037: /*----------------------------------------------------------------------------*/ 
0038: /* 構造体                                                                     */ 
0039: /*----------------------------------------------------------------------------*/ 
0040: /*数値タイプ列挙体*/ 
0041:  
0042: struct Attribute { 
0043:   char *str; 
0044:   int   cnt; 
0045: }; 
0046:  
0047: struct Node { 
0048:   char *element;               /*要素文字列*/ 
0049:   int   cnt;                   /*ノードの出現回数*/ 
0050:   struct Attribute *attribute; /*属性リスト*/ 
0051:   int attCnt;                  /*属性の種類数*/ 
0052:   struct Node  *parent; 
0053:   struct mssHash  *children; 
0054: }; 
0055:  
0056: typedef struct _XmlState { 
0057:   int level; 
0058: }XmlState; 
0059:  
0060: /*----------------------------------------------------------------------------*/ 
0061: /* グローバル変数                                                             */ 
0062: /*----------------------------------------------------------------------------*/ 
0063: extern struct mssGlobalVariables mssGV; 
0064: extern xmlParserCtxtPtr ctxt; 
0065: extern xmlParserCtxtPtr ctxt; 
0066:  
0067: static struct mssFPW    *fpw; /*出力ファイル構造体*/ 
0068: static struct mssHeader *hdo; /*出力ファイル用<head>タグ格納構造体*/ 
0069: static iconv_t *icid;   /*iconv用 変換ハンドラ*/ 
0070: static char *inEnc=NULL; /*エンコーディング*/ 
0071: static char *inVer=NULL; /*バージョン*/ 
0072: static char currentPath[256]; 
0073: static struct Node *currentNode; 
0074: static struct Node *tree; 
0075:  
0076: /*============================================================================*/ 
0077: /* オプション宣言&定義                                                       */ 
0078: /*============================================================================*/ 
0079: /*----------------------------------------------------------------------------*/ 
0080: /* 入力ファイル                                                               */ 
0081: /*----------------------------------------------------------------------------*/ 
0082:   MssOptINF optINF={ 
0083:     OINF,   /* オプションタイプ                                             */ 
0084:     "i",    /* キーワード(複数文字は不可)                                   */ 
0085:     0,      /* 0:オプション, 1:必須                                         */ 
0086:     1,      /* 指定可能の最大ファイル数                                     */ 
0087:     0,      /*1:file not foundのエラーで終了しない 0:する                   */ 
0088:     INFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0089:     INFC    /* このオプションのコメント(Helpで表示)                         */ 
0090:   }; 
0091:  
0092: /*----------------------------------------------------------------------------*/ 
0093: /* 出力ファイル                                                               */ 
0094: /*----------------------------------------------------------------------------*/ 
0095:   MssOptOTF optOTF={ 
0096:     OOTF,   /* オプションタイプ                                             */ 
0097:     "o",    /* キーワード(複数文字は不可)                                   */ 
0098:     0,      /* 0:オプション, 1:必須                                         */ 
0099:     OTFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0100:     OTFC    /* このオプションのコメント(Helpで表示)                         */ 
0101:   }; 
0102:  
0103: /*----------------------------------------------------------------------------*/ 
0104: /* 圧縮出力                                                                   */ 
0105: /*----------------------------------------------------------------------------*/ 
0106:   MssOptFLG optZIP={ 
0107:     OFLG,   /* オプションタイプ                                             */ 
0108:     "z",    /* キーワード(複数文字は不可)                                   */ 
0109:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0110:     ZIPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0111:     ZIPC    /* このオプションのコメント(Helpで表示)                         */ 
0112:   }; 
0113:  
0114: /*----------------------------------------------------------------------------*/ 
0115: /* オプションをまとめる                                                       */ 
0116: /*----------------------------------------------------------------------------*/ 
0117: void *opt[]={&optINF,&optOTF,&optZIP,NULL}; 
0118:  
0119: /*----------------------------------------------------------------------------*/ 
0120: /* ツリー構造の要素と属性をテーブル形式で書き出し                             */ 
0121: /*----------------------------------------------------------------------------*/ 
0122: void printTree(struct Node *node){ 
0123:   struct mssHashNode *hnode; 
0124:   char *pos; 
0125:   int i; 
0126:  
0127:   pos=currentPath+strlen(currentPath); 
0128:  
0129:   /*要素名の出力*/ 
0130:   if(node->element !=NULL){ /*トップノードは飛ばす */ 
0131:     /*現在のノードパスを更新*/ 
0132:     strcat(currentPath,"/"); 
0133:     strcat(currentPath,node->element); 
0134:  
0135:     mssWriteXmlContent(currentPath, icid, fpw); 
0136:     mssWriteDlm(fpw);  
0137:     mssWriteNull(fpw);  
0138:     mssWriteDlm(fpw);  
0139:     mssWriteInt(node->cnt,fpw); 
0140:     mssWriteRet(fpw); 
0141:     mssGV.outCnt++; 
0142:   } 
0143:  
0144:   /*属性を伴ったノードの出力*/ 
0145:   for(i=0; i<node->attCnt; i++){ 
0146:     mssWriteXmlContent(currentPath, icid, fpw); 
0147:     mssWriteDlm(fpw);  
0148:  
0149:     mssWriteXmlContent((node->attribute+i)->str, icid, fpw); 
0150:     mssWriteDlm(fpw);  
0151:  
0152:     mssWriteInt((node->attribute+i)->cnt,fpw); 
0153:     mssWriteRet(fpw); 
0154:     mssGV.outCnt++; 
0155:   } 
0156:   if(node->children==NULL) return; 
0157:  
0158:   for(i=0; i<node->children->hashVal; i++){ 
0159:     if( NULL != (hnode=*(node->children->node+i)) ){ 
0160:       while(hnode!=NULL){ 
0161:         printTree((struct Node *)(hnode->val.v.a)); 
0162:         hnode=hnode->next; 
0163:       } 
0164:     } 
0165:   } 
0166:  
0167:   /*現在のノードパスを更新*/ 
0168:   *pos='\0'; 
0169: } 
0170:  
0171: void freeTree(struct Node *node){ 
0172:   struct mssHashNode *hnode; 
0173:   int i; 
0174:  
0175:   if(node->children!=NULL){ 
0176:     if(node->attribute!=NULL){ 
0177:       mssFree(node->attribute); 
0178:     } 
0179:     for(i=0; i<node->children->hashVal; i++){ 
0180:       if( NULL != (hnode=*(node->children->node+i)) ){ 
0181:         while(hnode!=NULL){ 
0182:           freeTree((struct Node *)(hnode->val.v.a)); 
0183:           hnode=hnode->next; 
0184:         } 
0185:       } 
0186:     } 
0187:     mssFreeHash(node->children); 
0188:   } 
0189:  
0190:   if(node!=NULL) mssFree(node->element); 
0191:   mssFree(node); 
0192: } 
0193:  
0194: /*----------------------------------------------------------------------------*/ 
0195: /* SAX ハンドラー                                                             */ 
0196: /*----------------------------------------------------------------------------*/ 
0197: void start_doc(XmlState *state){ 
0198:   char *fldNam[3]={"element","attribute","count"}; 
0199:   char *fldNamEnc[3]; 
0200:   int i; 
0201:  
0202:   inEnc=mssStrdup((char *)ctxt->input->encoding); 
0203:   inVer=mssStrdup((char *)ctxt->version); 
0204:   if(inEnc==NULL) inEnc=mssStrdup("UTF-8"); 
0205:  
0206:   /*パラメータ用のiconvオープン                                   */ 
0207:   /*xmlコマンドのパラメータ、入力データ、出力データのencoding     */ 
0208:   /*は全て、入力データのエンコーディングとおなじことを前提に作る。*/ 
0209:   icid=iconv_open("UTF-8","euc-jp"); 
0210:   if((int)icid==-1) { 
0211:     mssShowErrMsg("encoding type error in iconv_open"); 
0212:     mssEnd(mssErrorNoDefault); 
0213:   } 
0214:   fldNamEnc[0]=mssEncoding(fldNam[0], icid); 
0215:   fldNamEnc[1]=mssEncoding(fldNam[1], icid); 
0216:   fldNamEnc[2]=mssEncoding(fldNam[2], icid); 
0217:  
0218:   /*パラメータ用のiconvクローズ*/ 
0219:   if(icid!=NULL) iconv_close(icid); 
0220:  
0221:   /*出力のiconvオープン*/ 
0222:   icid=iconv_open(inEnc,"UTF-8"); 
0223:   if((int)icid==-1) { 
0224:     mssShowErrMsg("encoding type error in iconv_open"); 
0225:     mssEnd(mssErrorNoDefault); 
0226:   } 
0227:  
0228:   /*出力ヘッダーの作成と出力   */ 
0229:   hdo=mssInitSetHeader(NULL, NULL, inVer, inEnc, MssXtDefVer); 
0230:  
0231:   for(i=0; i<3; i++){ 
0232:     mssAddFieldsByStr(hdo->flds, mssEncoding(fldNamEnc[i],icid)); 
0233:   } 
0234:  
0235:   /*xmlTableヘッダーの書き出し*/ 
0236:   mssWriteHeader(hdo, fpw); 
0237:  
0238:   /* currentPathの初期化 */ 
0239:   currentPath[0]='\0'; 
0240: } 
0241:  
0242: void end_doc(XmlState *state){ 
0243:   printTree(tree); 
0244:   freeTree(tree); 
0245:  
0246:   if(icid!=NULL) iconv_close(icid); 
0247:  
0248: } 
0249:  
0250: /*現在のNodeの子Nodeに指定されたelementがあれば、そのNodeを返す*/ 
0251: /*なければNULLを返す                                           */ 
0252: struct Node *getChildNode(struct Node *cn, char *element){ 
0253:   struct mssHashNode *node; 
0254:  
0255:   if( cn->element ==NULL) return(NULL); 
0256:   if( cn->children==NULL) return(NULL); 
0257:   node=(struct mssHashNode *) mssHashMember(cn->children, element); 
0258:  
0259:   if( NULL == node){ 
0260:     return(NULL); 
0261:   }else{ 
0262:     return((struct Node *)node->val.v.a); 
0263:   } 
0264: } 
0265:  
0266: void addAttribute(struct Node *node, char **atts){ 
0267:   int i,j; 
0268:   int flg; 
0269:  
0270:   if(atts!=NULL){ 
0271:     i=0; 
0272:     while(*(atts+i)!=NULL){ 
0273:  
0274:       /*既に存在していればcountUp+continue*/ 
0275:       flg=0; 
0276:       for(j=0; j<node->attCnt; j++){ 
0277:         if( 0==strcmp(*(atts+i),(node->attribute+j)->str) ){ 
0278:           (node->attribute+j)->cnt++; 
0279:           flg=1; 
0280:           break; 
0281:         } 
0282:       } 
0283:       if(flg){ 
0284:         i=i+2; 
0285:         continue; 
0286:       } 
0287:  
0288:       /*新規追加登録*/ 
0289:       node->attribute = mssRealloc(node->attribute, 
0290:         sizeof(struct Attribute)*(node->attCnt+1),"xmltree"); 
0291:       node->attribute->str=mssStrdup(*(atts+i)); 
0292:       node->attribute->cnt=1; 
0293:       i=i+2; 
0294:       node->attCnt++; 
0295:     } 
0296:   } 
0297: } 
0298:  
0299: struct Node *addNode(struct Node *cn, char *element, char **atts){ 
0300:   MssValue node; 
0301:  
0302:   /*新しいノードの確保*/ 
0303:   node.v.a=mssCalloc(sizeof(struct Node),"xmltree"); 
0304:  
0305:   /*エレメント名,新しいノードのアドレスをchildrenに登録*/ 
0306:   mssHashInsert(cn->children, element, node); 
0307:  
0308:   /*新しいノードの子ノードを初期化*/ 
0309:   ((struct Node *)(node.v.a))->children = mssInitHash(11); 
0310:   ((struct Node *)(node.v.a))->element  = mssStrdup(element); 
0311:   ((struct Node *)(node.v.a))->parent   = cn; 
0312:   ((struct Node *)(node.v.a))->attribute= NULL; 
0313:   ((struct Node *)(node.v.a))->attCnt   = 0; 
0314:   ((struct Node *)(node.v.a))->cnt      = 1; 
0315:  
0316:   return(node.v.a); 
0317: } 
0318:  
0319: /*エレメント start */ 
0320: void start_element(XmlState *state, char *fullname, char **atts){ 
0321:   struct Node *childNode; 
0322:  
0323:   mssGV.inCnt++; 
0324:   if(state->level>MAX_NEST){ 
0325:     mssShowErrMsg("nest level exceed (max=%d)" ,MAX_NEST); 
0326:     mssEnd(mssErrorNoDefault); 
0327:   } 
0328:  
0329:   /*エレメントの子ノードを得る*/ 
0330:   childNode=getChildNode(currentNode,fullname); 
0331:  
0332:   /*エレメントの子ノードが無ければ追加する*/ 
0333:   if( childNode==NULL ){ 
0334:     childNode=addNode(currentNode,fullname,atts); 
0335:   } 
0336:  
0337:   /*属性を追加*/ 
0338:   addAttribute(childNode, atts); 
0339:  
0340:   /*上の処理で得たエレメントの子ノードをカレントノードとする*/ 
0341:   currentNode=childNode; 
0342:   currentNode->cnt++; 
0343:  
0344:   state->level++; 
0345: } 
0346:  
0347: /*エレメント end */ 
0348: void end_element(XmlState *state, char *fullname, char **atts){ 
0349:   state->level--; 
0350:   if(state->level<0){ 
0351:     mssShowErrMsg("nest level reach to below 0"); 
0352:     mssEnd(mssErrorNoDefault); 
0353:   } 
0354:   currentNode=currentNode->parent; 
0355: } 
0356:  
0357: /*sax error handler*/ 
0358: #include "saxerror.h" 
0359:  
0360: static xmlSAXHandler SAXFunctions = { 
0361:     NULL, /* internalSubset */ 
0362:     NULL, /* isStandalone */ 
0363:     NULL, /* hasInternalSubset */ 
0364:     NULL, /* hasExternalSubset */ 
0365:     NULL, /* resolveEntity */ 
0366:     NULL, /* getEntity */ 
0367:     NULL, /* entityDecl */ 
0368:     NULL, /* notationDecl */ 
0369:     NULL, /* attributeDecl */ 
0370:     NULL, /* elementDecl */ 
0371:     NULL, /* unparsedEntityDecl */ 
0372:     NULL, /* setDocumentLocator */ 
0373:     (startDocumentSAXFunc)start_doc, /* startDocument */ 
0374:     (endDocumentSAXFunc)end_doc, /* endDocument */ 
0375:     (startElementSAXFunc)start_element, /* startElement */ 
0376:     (endElementSAXFunc)end_element, /* endElement */ 
0377:     NULL, /* reference */ 
0378:     NULL, /* characters */ 
0379:     NULL, /* ignorableWhitespace */ 
0380:     NULL, /* processingInstruction */ 
0381:     NULL, /* comment */ 
0382:     (warningSAXFunc) xmlSaxErrEnd, /* xmlParserWarning */ 
0383:     (errorSAXFunc) xmlSaxErrEnd, /* xmlParserError */ 
0384:     (fatalErrorSAXFunc) xmlSaxErrEnd, /* xmlParserError */ 
0385:     NULL, /* getParameterEntity */ 
0386: }; 
0387:  
0388: int main(int argc, char *argv[]){ 
0389:  
0390:   XmlState         *state; 
0391:  
0392: /*----------------------------------------------------------------------------*/ 
0393: /* 前処理                                                                     */ 
0394: /*----------------------------------------------------------------------------*/ 
0395:   mssInit(argc,argv,&comHelp);        /* シグナル処理などの初期化     */ 
0396:   mssHelpDoc(opt,&comHelp,argc,argv); /* ヘルプ                       */ 
0397:   mssSetOption(opt,argc,argv);        /* コマンドオプションの設定     */ 
0398:  
0399:   fpw=mssOpenFPW(optOTF.str,optZIP.set,0); /*標準出力オープン*/ 
0400:  
0401: /*----------------------------------------------------------------------------*/ 
0402: /*メインルーチン                                                              */ 
0403: /*----------------------------------------------------------------------------*/ 
0404:   tree=mssCalloc(sizeof(struct Node),"xmltree"); 
0405:   tree->children = mssInitHash(11); 
0406:   currentNode=tree; 
0407:  
0408:   state=mssCalloc(sizeof(XmlState),"xml2xt"); 
0409:  
0410:   if(optINF.set){ 
0411:     ctxt=(xmlParserCtxtPtr)xmlCreateFileParserCtxt(optINF.str); 
0412:   }else{ 
0413:     ctxt=(xmlParserCtxtPtr)xmlCreateFileParserCtxt("/dev/stdin"); 
0414:   } 
0415:   if(!ctxt){ 
0416:     mssShowErrMsg("not xml file\n"); 
0417:     mssEnd(mssErrorNoDefault); 
0418:   } 
0419:   ctxt->sax=&SAXFunctions; 
0420:  
0421:   ctxt->userData=state; 
0422:   xmlParseDocument(ctxt); 
0423:   ctxt->sax=NULL; 
0424:   xmlFreeParserCtxt(ctxt); 
0425:  
0426:   if(inEnc!=NULL) mssFree(inEnc); 
0427:   if(inVer!=NULL) mssFree(inVer); 
0428:   mssFree(state); 
0429:  
0430: /*----------------------------------------------------------------------------*/ 
0431: /*フッター出力&終了処理                                                       */ 
0432: /*----------------------------------------------------------------------------*/ 
0433:   mssWriteFooter(fpw);    /*フッターの出力           */ 
0434:   mssCloseFPW(fpw);       /*出力ファイルのクローズ   */ 
0435:   mssFreeHeader(hdo);     /*出力ヘッダ領域開放       */ 
0436:   mssFreeOption(opt);     /*オプション領域開放       */ 
0437:   mssShowEndMsg();        /*完了メッセージ           */ 
0438:   mssEnd(mssExitSuccess); /*終了                     */ 
0439:   return(0);              /* to avoid warning message*/ 
0440: }