MUSASHI C source: xmltree.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 <xmltreeHelp.h> 
0020: struct mssComHelp comHelp={ 
0021:   "xmltree",      /* コマンド名       */ 
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: struct Node { 
0041:   char  *element;               /*要素文字列*/ 
0042:   int    emptyTagFlg; 
0043:   char **atts;                  /*属性リスト*/ 
0044:   int    attCnt; 
0045:   struct Node  *parent; 
0046:   struct mssHash  *children; 
0047: }; 
0048:  
0049: typedef struct _XmlState { 
0050:   int level; 
0051:   int crFlg; 
0052: }XmlState; 
0053:  
0054: /*----------------------------------------------------------------------------*/ 
0055: /* グローバル変数                                                             */ 
0056: /*----------------------------------------------------------------------------*/ 
0057: extern struct mssGlobalVariables mssGV; 
0058: extern xmlParserCtxtPtr ctxt; 
0059:  
0060: static struct mssFPW    *fpw; /*出力ファイル構造体*/ 
0061: static iconv_t *icid;   /*iconv用 変換ハンドラ*/ 
0062: static char *inEnc=NULL; /*エンコーディング*/ 
0063: static char *inVer=NULL; /*バージョン*/ 
0064: static struct Node *currentNode; 
0065: static struct Node *tree; 
0066:  
0067: /*============================================================================*/ 
0068: /* オプション宣言&定義                                                       */ 
0069: /*============================================================================*/ 
0070: /*----------------------------------------------------------------------------*/ 
0071: /* 入力ファイル                                                               */ 
0072: /*----------------------------------------------------------------------------*/ 
0073:   MssOptINF optINF={ 
0074:     OINF,   /* オプションタイプ                                             */ 
0075:     "i",    /* キーワード(複数文字は不可)                                   */ 
0076:     0,      /* 0:オプション, 1:必須                                         */ 
0077:     1,      /* 指定可能の最大ファイル数                                     */ 
0078:     0,      /*1:file not foundのエラーで終了しない 0:する                   */ 
0079:     INFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0080:     INFC    /* このオプションのコメント(Helpで表示)                         */ 
0081:   }; 
0082:  
0083: /*----------------------------------------------------------------------------*/ 
0084: /* 出力ファイル                                                               */ 
0085: /*----------------------------------------------------------------------------*/ 
0086:   MssOptOTF optOTF={ 
0087:     OOTF,   /* オプションタイプ                                             */ 
0088:     "o",    /* キーワード(複数文字は不可)                                   */ 
0089:     0,      /* 0:オプション, 1:必須                                         */ 
0090:     OTFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0091:     OTFC    /* このオプションのコメント(Helpで表示)                         */ 
0092:   }; 
0093:  
0094: /*----------------------------------------------------------------------------*/ 
0095: /* 圧縮出力                                                                   */ 
0096: /*----------------------------------------------------------------------------*/ 
0097:   MssOptFLG optZIP={ 
0098:     OFLG,   /* オプションタイプ                                             */ 
0099:     "z",    /* キーワード(複数文字は不可)                                   */ 
0100:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0101:     ZIPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0102:     ZIPC    /* このオプションのコメント(Helpで表示)                         */ 
0103:   }; 
0104:  
0105: /*----------------------------------------------------------------------------*/ 
0106: /* オプションをまとめる                                                       */ 
0107: /*----------------------------------------------------------------------------*/ 
0108: void *opt[]={&optINF,&optOTF,&optZIP,NULL}; 
0109:  
0110: /*----------------------------------------------------------------------------*/ 
0111: /* ツリー構造の要素と属性を書き出し                                           */ 
0112: /*----------------------------------------------------------------------------*/ 
0113: int Level=-1; 
0114: void printTree(struct Node *node){ 
0115:   struct mssHashNode *hnode; 
0116:   struct mssXmlTag *xmlTag; 
0117:   int i; 
0118:  
0119:   if(node->element !=NULL){ 
0120:     mssWriteXmlIndent(Level,fpw); 
0121:     xmlTag=mssInitXmlTag(node->element,NULL); 
0122:     if(node->atts!=NULL){ 
0123:       for(i=0;;i++){ 
0124:         if(*(node->atts+2*i+0)==NULL) break; 
0125:         if(*(node->atts+2*i+1)==NULL) break; 
0126:         mssAddXmlTagAttributeStr(xmlTag,*(node->atts+2*i), 
0127:                                         *(node->atts+2*i+1),NULL); 
0128:       } 
0129:     }  
0130:  
0131:     if(node->emptyTagFlg){ 
0132:       mssWriteXmlEmptyTag(xmlTag,icid,fpw); 
0133:       mssGV.outCnt++; 
0134:       mssWriteRet(fpw); 
0135:       return; 
0136:     }else{ 
0137:       mssWriteXmlStartTag(xmlTag,icid,fpw); 
0138:       mssGV.outCnt++; 
0139:     } 
0140:     mssFreeXmlTag(xmlTag); 
0141:  
0142:     if(node->children->cnt!=0){ 
0143:       mssWriteRet(fpw); 
0144:     } 
0145:   } 
0146:  
0147:   if(node->children==NULL) return; 
0148:  
0149:   for(i=0; i<node->children->hashVal; i++){ 
0150:     if( NULL != (hnode=*(node->children->node+i)) ){ 
0151:       while(hnode!=NULL){ 
0152:         Level++; 
0153:         printTree((struct Node *)(hnode->val.v.a)); 
0154:         Level--; 
0155:         hnode=hnode->next; 
0156:       } 
0157:     } 
0158:   } 
0159:  
0160:   if(node->element !=NULL){ 
0161:     if(node->children->cnt!=0){ 
0162:       mssWriteXmlIndent(Level,fpw); 
0163:     } 
0164:  
0165:     xmlTag=mssInitXmlTag(node->element,NULL); 
0166:     mssWriteXmlEndTag(xmlTag,icid,fpw); 
0167:     mssFreeXmlTag(xmlTag); 
0168:     mssWriteRet(fpw); 
0169:   } 
0170: } 
0171:  
0172: void freeTree(struct Node *node){ 
0173:   struct mssHashNode *hnode; 
0174:   int i; 
0175:  
0176:   if(node->children!=NULL){ 
0177:     if(node->atts!=NULL){ 
0178:       for(i=0; i<node->attCnt; i++){ 
0179:         mssFree( *(node->atts+i*2+0) ); 
0180:         mssFree( *(node->atts+i*2+1) ); 
0181:       } 
0182:       mssFree(node->atts); 
0183:     } 
0184:     for(i=0; i<node->children->hashVal; i++){ 
0185:       if( NULL != (hnode=*(node->children->node+i)) ){ 
0186:         while(hnode!=NULL){ 
0187:           freeTree((struct Node *)(hnode->val.v.a)); 
0188:           hnode=hnode->next; 
0189:         } 
0190:       } 
0191:     } 
0192:     mssFreeHash(node->children); 
0193:   } 
0194:  
0195:   if(node!=NULL) mssFree(node->element); 
0196:   mssFree(node); 
0197: } 
0198:  
0199: /*----------------------------------------------------------------------------*/ 
0200: /* SAX ハンドラー                                                             */ 
0201: /*----------------------------------------------------------------------------*/ 
0202: void start_doc(XmlState *state){ 
0203:  
0204:   inEnc=mssStrdup((char *)ctxt->input->encoding); 
0205:   inVer=mssStrdup((char *)ctxt->version); 
0206:   mssWriteXmlDeclaration( inVer, inEnc, fpw ); 
0207:   if(inEnc==NULL) inEnc=mssStrdup("UTF-8"); 
0208:  
0209:  
0210:   /*出力のiconvオープン*/ 
0211:   icid=iconv_open(inEnc,"UTF-8"); 
0212:   if((int)icid==-1){ 
0213:       mssShowErrMsg("encoding type error in iconv_open"); 
0214:       mssEnd(mssErrorNoDefault); 
0215:   } 
0216: } 
0217:  
0218: void end_doc(XmlState *state){ 
0219:   printTree(tree); 
0220:   freeTree(tree); 
0221:  
0222:   if(icid!=NULL) iconv_close(icid); 
0223: } 
0224:  
0225: /*現在のNodeの子Nodeに指定されたelementがあれば、そのNodeを返す*/ 
0226: /*なければNULLを返す                                           */ 
0227: struct Node *getChildNode(struct Node *cn, char *element){ 
0228:   struct mssHashNode *node; 
0229:  
0230:   if( cn->element==NULL) return(NULL); 
0231:   if( cn->children==NULL) return(NULL); 
0232:   node=(struct mssHashNode *) mssHashMember(cn->children, element); 
0233:  
0234:   if( NULL == node){ 
0235:     return(NULL); 
0236:   }else{ 
0237:     return((struct Node *)node->val.v.a); 
0238:   } 
0239: } 
0240:  
0241:  
0242: struct Node *addNode(struct Node *cn, char *element){ 
0243:   MssValue node; 
0244:  
0245:   /*新しいノードの確保*/ 
0246:   node.v.a=mssCalloc(sizeof(struct Node),"xmltree"); 
0247:  
0248:   /*エレメント名,新しいノードのアドレスをchildrenに登録*/ 
0249:   mssHashInsert(cn->children, element, node); 
0250:  
0251:   /*新しいノードの子ノードを初期化*/ 
0252:   ((struct Node *)(node.v.a))->children    = mssInitHash(11); 
0253:   ((struct Node *)(node.v.a))->element     = mssStrdup(element); 
0254:   ((struct Node *)(node.v.a))->emptyTagFlg = 0; 
0255:   ((struct Node *)(node.v.a))->parent      = cn; 
0256:   ((struct Node *)(node.v.a))->atts        = NULL; 
0257:   ((struct Node *)(node.v.a))->attCnt      = 0; 
0258:  
0259:   return(node.v.a); 
0260: } 
0261:  
0262: void addAtts(struct Node *node, char **atts){ 
0263:   int i,j; 
0264:   int flg; 
0265:    
0266:   if(atts!=NULL){ 
0267:     i=0; 
0268:     while(*(atts+i)!=NULL){ 
0269:      
0270:       /*既に存在していればcontinue*/ 
0271:       flg=0; 
0272:       for(j=0; j<node->attCnt; j++){ 
0273:         if( 0==strcmp(*(atts+i),*(node->atts+j*2)) ){ 
0274:           flg=1; 
0275:           break; 
0276:         } 
0277:       } 
0278:       if(flg){ 
0279:         i=i+2; 
0280:         continue; 
0281:       } 
0282:  
0283:       /*追加登録*/ 
0284:       node->atts = mssRealloc(node->atts, 
0285:         sizeof(char *)*((node->attCnt+2)*2),"xmltree"); 
0286:       *(node->atts+node->attCnt*2+0)=mssStrdup(*(atts+i)); 
0287:       *(node->atts+node->attCnt*2+1)=mssStrdup(""); 
0288:       *(node->atts+node->attCnt*2+2)=NULL; 
0289:       *(node->atts+node->attCnt*2+3)=NULL; 
0290:       i=i+2; 
0291:       node->attCnt++; 
0292:     } 
0293:   } 
0294: } 
0295:  
0296: /*エレメント start */ 
0297: void start_element(XmlState *state, char *fullname, char **atts){ 
0298:   struct Node *childNode; 
0299:  
0300:   mssGV.inCnt++; 
0301:   if(state->level>MAX_NEST){ 
0302:     mssShowErrMsg("nest level exceed (max=%d)" ,MAX_NEST); 
0303:     mssEnd(mssErrorNoDefault); 
0304:   } 
0305:  
0306:   /*エレメントの子ノードを得る*/ 
0307:   childNode=getChildNode(currentNode,fullname); 
0308:  
0309:   /*エレメントの子ノードが無ければ追加する*/ 
0310:   if( childNode==NULL ){ 
0311:     childNode=addNode(currentNode,fullname); 
0312:   } 
0313:  
0314:   /*属性を追加*/ 
0315:   addAtts(childNode,atts); 
0316:  
0317:   /*上の処理で得たエレメントの子ノードをカレントノードとする*/ 
0318:   currentNode=childNode; 
0319:  
0320:   state->level++; 
0321: } 
0322:  
0323: /*エレメント end */ 
0324: void end_element(XmlState *state, char *fullname, char **atts){ 
0325:   state->level--; 
0326:   if(state->level<0){ 
0327:     mssShowErrMsg("nest level reach to below 0"); 
0328:     mssEnd(mssErrorNoDefault); 
0329:   } 
0330:   currentNode=currentNode->parent; 
0331: } 
0332:  
0333: /*sax error handler*/ 
0334: #include "saxerror.h" 
0335:  
0336: static xmlSAXHandler SAXFunctions = { 
0337:     NULL, /* internalSubset */ 
0338:     NULL, /* isStandalone */ 
0339:     NULL, /* hasInternalSubset */ 
0340:     NULL, /* hasExternalSubset */ 
0341:     NULL, /* resolveEntity */ 
0342:     NULL, /* getEntity */ 
0343:     NULL, /* entityDecl */ 
0344:     NULL, /* notationDecl */ 
0345:     NULL, /* attributeDecl */ 
0346:     NULL, /* elementDecl */ 
0347:     NULL, /* unparsedEntityDecl */ 
0348:     NULL, /* setDocumentLocator */ 
0349:     (startDocumentSAXFunc)start_doc, /* startDocument */ 
0350:     (endDocumentSAXFunc)end_doc, /* endDocument */ 
0351:     (startElementSAXFunc)start_element, /* startElement */ 
0352:     (endElementSAXFunc)end_element, /* endElement */ 
0353:     NULL, /* reference */ 
0354:     NULL, /* characters */ 
0355:     NULL, /* ignorableWhitespace */ 
0356:     NULL, /* processingInstruction */ 
0357:     NULL, /* comment */ 
0358:     (warningSAXFunc) xmlSaxErrEnd, /* xmlParserWarning */ 
0359:     (errorSAXFunc) xmlSaxErrEnd, /* xmlParserError */ 
0360:     (fatalErrorSAXFunc) xmlSaxErrEnd, /* xmlParserError */ 
0361:     NULL, /* getParameterEntity */ 
0362: }; 
0363:  
0364: int main(int argc, char *argv[]){ 
0365:  
0366:   XmlState         *state; 
0367:  
0368: /*----------------------------------------------------------------------------*/ 
0369: /* 前処理                                                                     */ 
0370: /*----------------------------------------------------------------------------*/ 
0371:   mssInit(argc,argv,&comHelp);        /* シグナル処理などの初期化     */ 
0372:   mssHelpDoc(opt,&comHelp,argc,argv); /* ヘルプ                       */ 
0373:   mssSetOption(opt,argc,argv);        /* コマンドオプションの設定     */ 
0374:  
0375:   fpw=mssOpenFPW(optOTF.str,optZIP.set,0); /*標準出力オープン*/ 
0376:  
0377: /*----------------------------------------------------------------------------*/ 
0378: /*メインルーチン                                                              */ 
0379: /*----------------------------------------------------------------------------*/ 
0380:   tree=mssCalloc(sizeof(struct Node),"xmltree"); 
0381:   tree->children = mssInitHash(11); 
0382:   currentNode=tree; 
0383:  
0384:   state=mssCalloc(sizeof(XmlState),"xml2xt"); 
0385:  
0386:   if(optINF.set){ 
0387:     ctxt=(xmlParserCtxtPtr)xmlCreateFileParserCtxt(optINF.str); 
0388:   }else{ 
0389:     ctxt=(xmlParserCtxtPtr)xmlCreateFileParserCtxt("/dev/stdin"); 
0390:   } 
0391:   if(!ctxt){ 
0392:     mssShowErrMsg("not xml file\n"); 
0393:     mssEnd(mssErrorNoDefault); 
0394:   } 
0395:   ctxt->sax=&SAXFunctions; 
0396:  
0397:   ctxt->userData=state; 
0398:   xmlParseDocument(ctxt); 
0399:   ctxt->sax=NULL; 
0400:   xmlFreeParserCtxt(ctxt); 
0401:  
0402:   mssFree(inEnc); 
0403:   mssFree(inVer); 
0404:   mssFree(state); 
0405:  
0406: /*----------------------------------------------------------------------------*/ 
0407: /*フッター出力&終了処理                                                       */ 
0408: /*----------------------------------------------------------------------------*/ 
0409:   mssCloseFPW(fpw);       /*出力ファイルのクローズ   */ 
0410:   mssFreeOption(opt);     /*オプション領域開放       */ 
0411:   mssShowEndMsg();        /*完了メッセージ           */ 
0412:   mssEnd(mssExitSuccess); /*終了                     */ 
0413:   return(0);              /* to avoid warning message*/ 
0414: }