MUSASHI C source: xmlhead.c


0001:  
0002: /*============================================================================*/ 
0003: /* 変更履歴                                                                   */ 
0004: /*----------------------------------------------------------------------------*/ 
0005: /* 1.0 : 新しいAPIに対応                                                      */ 
0006: /*============================================================================*/ 
0007: #include <musashi.h
0008: #include <stdio.h> 
0009: #include <stdlib.h> 
0010: #include <string.h> 
0011: #include <limits.h> 
0012: #include <libxml/parser.h> 
0013: #include <libxml/parserInternals.h> 
0014: #include <libxml/encoding.h> 
0015: #include <iconv.h> 
0016: #include <errno.h> 
0017: #include <glob.h> 
0018:  
0019: #include <xmlheadHelp.h> 
0020: struct mssComHelp comHelp={ 
0021:   "xmlhead",    /* コマンド名       */ 
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: extern struct mssGlobalVariables mssGV; 
0041: extern xmlParserCtxtPtr ctxt; 
0042:  
0043: static struct mssFPW    *fpw; /*出力ファイル構造体*/ 
0044: static iconv_t *icid;   /*iconv用 変換ハンドラ*/ 
0045: static char *inEnc=NULL; /*一つ目のファイルのエンコーディング*/ 
0046: static char *inVer=NULL; /*一つ目のファイルのバージョン*/ 
0047: static char  currentPath[4096]; /*現在処理中のパス (/a/b/c/)*/ 
0048:  
0049: /*----------------------------------------------------------------------------*/ 
0050: /* 整数型                                                                     */ 
0051: /*----------------------------------------------------------------------------*/ 
0052:   MssOptINT optLIN={ 
0053:     OINT,   /* オプションタイプ                                             */ 
0054:     "l",    /* キーワード(複数文字は不可)                                   */ 
0055:     0,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0056:     10,     /* デフォルト(数値として指定)                                   */ 
0057:     1,      /* 最小値                                                       */ 
0058:     INT_MAX,/* 最大値                                                       */ 
0059:     LINT,   /* このオプションのタイトル(Helpで表示)                         */ 
0060:     LINC    /* このオプションのコメント(Helpで表示)                         */ 
0061:   }; 
0062:  
0063: /*----------------------------------------------------------------------------*/ 
0064: /* 入力ファイル                                                               */ 
0065: /*----------------------------------------------------------------------------*/ 
0066:   MssOptINF optINF={ 
0067:     OINF,   /* オプションタイプ                                             */ 
0068:     "i",    /* キーワード(複数文字は不可)                                   */ 
0069:     0,      /* 0:オプション, 1:必須                                         */ 
0070:     256,    /* 指定可能の最大ファイル数                                     */ 
0071:     0,      /*1:file not foundのエラーで終了しない 0:する                   */ 
0072:     INFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0073:     INFC    /* このオプションのコメント(Helpで表示)                         */ 
0074:   }; 
0075:  
0076: /*----------------------------------------------------------------------------*/ 
0077: /* 出力ファイル                                                               */ 
0078: /*----------------------------------------------------------------------------*/ 
0079:   MssOptOTF optOTF={ 
0080:     OOTF,   /* オプションタイプ                                             */ 
0081:     "o",    /* キーワード(複数文字は不可)                                   */ 
0082:     0,      /* 0:オプション, 1:必須                                         */ 
0083:     OTFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0084:     OTFC    /* このオプションのコメント(Helpで表示)                         */ 
0085:   }; 
0086:  
0087: /*----------------------------------------------------------------------------*/ 
0088: /* 圧縮出力                                                                   */ 
0089: /*----------------------------------------------------------------------------*/ 
0090:   MssOptFLG optZIP={ 
0091:     OFLG,   /* オプションタイプ                                             */ 
0092:     "z",    /* キーワード(複数文字は不可)                                   */ 
0093:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0094:     ZIPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0095:     ZIPC    /* このオプションのコメント(Helpで表示)                         */ 
0096:   }; 
0097:  
0098: /*----------------------------------------------------------------------------*/ 
0099: /* オプションをまとめる                                                       */ 
0100: /*----------------------------------------------------------------------------*/ 
0101: void *opt[]={&optLIN,&optINF,&optOTF,&optZIP,NULL}; 
0102:  
0103: /*----------------------------------------------------------------------------*/ 
0104: /* 構造体                                                                     */ 
0105: /*----------------------------------------------------------------------------*/ 
0106:  
0107: /* -f 項目名構造体 */ 
0108: /* ex) -f rec@id:recID */ 
0109: struct XmlFld { 
0110:   int   cnt;               /*項目数         */ 
0111:   char *eleNamOrg[MssFieldMaxCnt]; /*要素名 (rec)   */ 
0112:   char *attNamOrg[MssFieldMaxCnt]; /*属性名 (id)    */ 
0113:   char *newNamOrg[MssFieldMaxCnt]; /*新項目名(recID)*/ 
0114:   char *eleNam[MssFieldMaxCnt];    /*要素名UTF8     */ 
0115:   char *attNam[MssFieldMaxCnt];    /*属性名UTF8     */ 
0116:   char *newNam[MssFieldMaxCnt];    /*新項目名UTF8   */ 
0117:   int   keyNum[MssFieldMaxCnt];    /*-kでも指定されていれば、その番号*/ 
0118: }; 
0119:  
0120: struct XmlKey { 
0121:   char *namOrg[MssFieldMaxCnt]; 
0122:   char *nam[MssFieldMaxCnt]; 
0123:   int   on[MssFieldMaxCnt]; 
0124:   int   allKeyIsOn; 
0125:   int   cnt; 
0126: }; 
0127:  
0128: typedef struct _XmlState { 
0129:   int level; 
0130:   int crFlg; 
0131:   int tagCnt; /*スタートタグの出現回数(この数値を元にセレクトする)*/ 
0132: } XmlState; 
0133:  
0134: void endOfProgram(XmlState *state){ 
0135:  
0136:   mssFree(inEnc); 
0137:   mssFree(inVer); 
0138:   mssFree(state); 
0139:  
0140: /*----------------------------------------------------------------------------*/ 
0141: /*フッター出力&終了処理                                                       */ 
0142: /*----------------------------------------------------------------------------*/ 
0143:   mssCloseFPW(fpw);     /*出力ファイルのクローズ*/ 
0144:   mssFreeOption(opt);      /*オプション領域開放*/ 
0145:   mssShowEndMsg();        /*完了メッセージ           */ 
0146:   mssEnd(mssExitSuccess); /*終了                     */ 
0147: } 
0148:  
0149: /*----------------------------------------------------------------------------*/ 
0150: /* SAX ハンドラー                                                             */ 
0151: /*----------------------------------------------------------------------------*/ 
0152: void start_doc(XmlState *state){ 
0153:  
0154:   /*XML宣言を獲得し出力*/ 
0155:   inEnc=mssStrdup((char *)ctxt->input->encoding); 
0156:   inVer=mssStrdup((char *)ctxt->version); 
0157:   mssWriteXmlDeclaration( inVer, inEnc, fpw ); 
0158:   if(inEnc==NULL) inEnc=mssStrdup("UTF-8"); 
0159:  
0160:   /*出力のiconvオープン*/ 
0161:   icid=iconv_open(inEnc,"UTF-8"); 
0162:   if((int)icid==-1) { 
0163:     mssShowErrMsg("encoding type error in iconv_open"); 
0164:     mssEnd(mssErrorNoDefault); 
0165:   } 
0166:  
0167:   /* currentPathの初期化 */ 
0168:   currentPath[0]='/'; 
0169:   currentPath[1]='\0'; 
0170:  
0171: } 
0172:  
0173: void end_doc(XmlState *state){ 
0174:   if(icid!=NULL) iconv_close(icid); 
0175: } 
0176:  
0177: /*エレメント start */ 
0178: void start_element(XmlState *state, char *fullname, char **atts){ 
0179:   struct mssXmlTag *xmlTag; 
0180:   char *pos; 
0181:   int i; 
0182:  
0183:   /*タグの出現件数がoptLINを超えたら終了*/ 
0184:   state->tagCnt++; 
0185:   if(state->tagCnt>optLIN.val){ 
0186:     mssWriteRet(fpw); 
0187:     pos=currentPath+strlen(currentPath)-1; 
0188:     while(pos>currentPath){ 
0189:       state->level--; 
0190:       *pos='\0'; 
0191:       while(*pos!='/') pos--; 
0192:       mssWriteXmlIndent(state->level,fpw); 
0193:       xmlTag=mssInitXmlTag(pos+1,NULL); 
0194:       mssWriteXmlEndTag(xmlTag,icid,fpw); 
0195:       mssFreeXmlTag(xmlTag); 
0196:       mssWriteRet(fpw); 
0197:     } 
0198:     endOfProgram(state); 
0199:   } 
0200:  
0201:   mssGV.inCnt++; 
0202:  
0203:   /*現在のノードパスを更新*/ 
0204:   strcat(currentPath,fullname); 
0205:   strcat(currentPath,"/"); 
0206:  
0207:   if(state->crFlg){ 
0208:     mssWriteRet(fpw); 
0209:     state->crFlg=0; 
0210:   } 
0211:   mssWriteXmlIndent(state->level,fpw); 
0212:   xmlTag=mssInitXmlTag(fullname,NULL); 
0213:   if(atts!=NULL){ 
0214:     for(i=0;;i++){ 
0215:       if(*(atts+2*i+0)==NULL) break; 
0216:       if(*(atts+2*i+1)==NULL) break; 
0217:       mssAddXmlTagAttributeStr(xmlTag,*(atts+2*i),*(atts+2*i+1),NULL); 
0218:     } 
0219:   } 
0220:   mssWriteXmlStartTag(xmlTag,icid,fpw); 
0221:   mssFreeXmlTag(xmlTag); 
0222:   mssGV.outCnt++; 
0223:   state->level++; 
0224: } 
0225:  
0226: /*エレメント end */ 
0227: void end_element(XmlState *state, char *fullname, char **atts){ 
0228:   struct mssXmlTag *xmlTag; 
0229:   char *pos; 
0230:  
0231:   state->level--; 
0232:   if(state->crFlg){ 
0233:     mssWriteRet(fpw); 
0234:     mssWriteXmlIndent(state->level,fpw); 
0235:     state->crFlg=0; 
0236:   } 
0237:   xmlTag=mssInitXmlTag(fullname,NULL); 
0238:   mssWriteXmlEndTag(xmlTag,icid,fpw); 
0239:   mssFreeXmlTag(xmlTag); 
0240:  
0241:   /*現在のノードパスを更新*/ 
0242:   pos=currentPath+strlen(currentPath)-2; 
0243:   while(*pos!='/') pos--; 
0244:   *(++pos)='\0'; 
0245:  
0246: } 
0247:  
0248: void start_characters(XmlState *state, xmlChar *chars, int len){ 
0249:   char *tmp; 
0250:   switch(*chars){ 
0251:   case '\n': 
0252:     state->crFlg=1; break; 
0253:   case '&': 
0254:     mssWriteStr("&amp;",fpw); break; 
0255:   case '>': 
0256:     mssWriteStr("&gt;",fpw); break; 
0257:   case '<': 
0258:     mssWriteStr("&lt;",fpw); break; 
0259:   case '\'': 
0260:     mssWriteStr("&apos;",fpw); break; 
0261:   case '"': 
0262:     mssWriteStr("&quot;",fpw); break; 
0263:   default: 
0264:     tmp=mssNencoding(chars,len,icid); 
0265:     mssWriteStr(tmp,fpw); 
0266:     mssFree(tmp); 
0267:   } 
0268: } 
0269:  
0270: void start_cdata(XmlState *state, xmlChar *chars, int len){ 
0271:   char *tmp; 
0272:   mssWriteStr("<![CDATA[",fpw); 
0273:   tmp=mssNencoding(chars,len,icid); 
0274:   mssWriteStr(tmp,fpw); 
0275:   mssFree(tmp); 
0276:   mssWriteStr("]]>",fpw); 
0277: } 
0278:  
0279: static xmlEntityPtr get_entity( XmlState *ctx, xmlChar *name){ 
0280:   return xmlGetPredefinedEntity(name); 
0281: } 
0282:  
0283: /*sax error handler*/ 
0284: #include "saxerror.h" 
0285:  
0286: static xmlSAXHandler SAXFunctions = { 
0287:     NULL, /* internalSubset */ 
0288:     NULL, /* isStandalone */ 
0289:     NULL, /* hasInternalSubset */ 
0290:     NULL, /* hasExternalSubset */ 
0291:     NULL, /* resolveEntity */ 
0292:     (getEntitySAXFunc) get_entity, /* getEntity */ 
0293:     NULL, /* entityDecl */ 
0294:     NULL, /* notationDecl */ 
0295:     NULL, /* attributeDecl */ 
0296:     NULL, /* elementDecl */ 
0297:     NULL, /* unparsedEntityDecl */ 
0298:     NULL, /* setDocumentLocator */ 
0299:     (startDocumentSAXFunc)start_doc, /* startDocument */ 
0300:     (endDocumentSAXFunc)end_doc, /* endDocument */ 
0301:     (startElementSAXFunc)start_element, /* startElement */ 
0302:     (endElementSAXFunc)end_element, /* endElement */ 
0303:     NULL, /* reference */ 
0304:     (charactersSAXFunc) start_characters, /* characters */ 
0305:     NULL, /* ignorableWhitespace */ 
0306:     NULL, /* processingInstruction */ 
0307:     NULL, /* comment */ 
0308:     (warningSAXFunc) xmlSaxErrEnd, /* xmlParserWarning */ 
0309:     (errorSAXFunc) xmlSaxErrEnd, /* xmlParserError */ 
0310:     (fatalErrorSAXFunc) xmlSaxErrEnd, /* xmlParserError */ 
0311:     NULL, /* getParameterEntity */ 
0312:     (cdataBlockSAXFunc)start_cdata, 
0313: }; 
0314:  
0315: int main(int argc, char *argv[]){ 
0316:  
0317:   XmlState         *state; 
0318:  
0319: /*----------------------------------------------------------------------------*/ 
0320: /* 前処理                                                                     */ 
0321: /*----------------------------------------------------------------------------*/ 
0322:   mssInit(argc,argv,&comHelp);        /* シグナル処理などの初期化     */ 
0323:   mssHelpDoc(opt,&comHelp,argc,argv); /* ヘルプ                       */ 
0324:   mssSetOption(opt,argc,argv);        /* コマンドオプションの設定     */ 
0325:  
0326:   fpw=mssOpenFPW(optOTF.str,optZIP.set,0); /*標準出力オープン*/ 
0327:  
0328: /*----------------------------------------------------------------------------*/ 
0329: /*メインルーチン                                                              */ 
0330: /*----------------------------------------------------------------------------*/ 
0331:  
0332:   state=mssCalloc(sizeof(XmlState),"xml2xt"); 
0333:  
0334:   ctxt=(xmlParserCtxtPtr)xmlCreateFileParserCtxt(*(optINF.strList+0)); 
0335:   if(!ctxt){ 
0336:     mssShowErrMsg("not xml file\n"); 
0337:     mssEnd(mssErrorNoDefault); 
0338:   } 
0339:   ctxt->sax=&SAXFunctions; 
0340:  
0341:   ctxt->userData=state; 
0342:   xmlParseDocument(ctxt); 
0343:   ctxt->sax=NULL; 
0344:   xmlFreeParserCtxt(ctxt); 
0345:  
0346: /*----------------------------------------------------------------------------*/ 
0347: /*終了処理                                                                    */ 
0348: /*----------------------------------------------------------------------------*/ 
0349:   endOfProgram(state); 
0350:   return(0);              /* to avoid warning message*/ 
0351: }