MUSASHI C source: xmlenc.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:  
0018: #include <xmlencHelp.h> 
0019: struct mssComHelp comHelp={ 
0020:   "xmlenc",       /* コマンド名       */ 
0021:   "1.0",          /* バージョン       */ 
0022:   HELPT,          /* コマンドタイトル */ 
0023:   HELPS,          /* 要約             */ 
0024:   HELPE,          /* 利用例           */ 
0025:   HELPR,          /* 参照コマンド     */ 
0026:   HELPA,          /* 作者情報         */ 
0027:   HELPB,          /* バグレポート情報 */ 
0028:   HELPH           /* ホームページ     */ 
0029: }; 
0030:  
0031: #define UNDEF 0 
0032: #define MAX_NEST 32 
0033: #define LOCAL_BUF 256 
0034: #define EncMax MssFieldMaxLen  /*iconvで使う出力用文字列長*/ 
0035:  
0036: /*----------------------------------------------------------------------------*/ 
0037: /* グローバル変数                                                             */ 
0038: /*----------------------------------------------------------------------------*/ 
0039: extern xmlParserCtxtPtr ctxt; 
0040: extern struct mssGlobalVariables mssGV; 
0041:  
0042: struct mssFPW    *fpw; /*出力ファイル構造体*/ 
0043: iconv_t *icid;   /*iconv用 変換ハンドラ*/ 
0044: char *inEnc=NULL; /*エンコーディング*/ 
0045: char *inVer=NULL; /*バージョン*/ 
0046:  
0047: /*----------------------------------------------------------------------------*/ 
0048: /* encoding名                                                                 */ 
0049: /*----------------------------------------------------------------------------*/ 
0050:   MssOptSTR optENC={ 
0051:     OSTR,   /* オプションタイプ                                             */ 
0052:     "e",    /* キーワード(複数文字は不可)                                   */ 
0053:     1,      /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視)      */ 
0054:     NULL  , /* デフォルト                                                   */ 
0055:     1,      /* 文字列の最小長                                               */ 
0056:     50,     /* 文字列の最大長                                               */ 
0057:     ENCT,   /* このオプションのタイトル(Helpで表示)                         */ 
0058:     ENCC    /* このオプションのコメント(Helpで表示)                         */ 
0059:   }; 
0060:  
0061: /*----------------------------------------------------------------------------*/ 
0062: /* 入力ファイル                                                               */ 
0063: /*----------------------------------------------------------------------------*/ 
0064:   MssOptINF optINF={ 
0065:     OINF,   /* オプションタイプ                                             */ 
0066:     "i",    /* キーワード(複数文字は不可)                                   */ 
0067:     0,      /* 0:オプション, 1:必須                                         */ 
0068:     1,      /* 指定可能の最大ファイル数                                     */ 
0069:     0,      /*1:file not foundのエラーで終了しない 0:する                   */ 
0070:     INFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0071:     INFC    /* このオプションのコメント(Helpで表示)                         */ 
0072:   }; 
0073:  
0074: /*----------------------------------------------------------------------------*/ 
0075: /* 出力ファイル                                                               */ 
0076: /*----------------------------------------------------------------------------*/ 
0077:   MssOptOTF optOTF={ 
0078:     OOTF,   /* オプションタイプ                                             */ 
0079:     "o",    /* キーワード(複数文字は不可)                                   */ 
0080:     0,      /* 0:オプション, 1:必須                                         */ 
0081:     OTFT,   /* このオプションのタイトル(Helpで表示)                         */ 
0082:     OTFC    /* このオプションのコメント(Helpで表示)                         */ 
0083:   }; 
0084:  
0085: /*----------------------------------------------------------------------------*/ 
0086: /* 圧縮出力                                                                   */ 
0087: /*----------------------------------------------------------------------------*/ 
0088:   MssOptFLG optZIP={ 
0089:     OFLG,   /* オプションタイプ                                             */ 
0090:     "z",    /* キーワード(複数文字は不可)                                   */ 
0091:     0,      /* デフォルト(基本的には0) 常にonにしたいときは1にする          */ 
0092:     ZIPT,   /* このオプションのタイトル(Helpで表示)                         */ 
0093:     ZIPC    /* このオプションのコメント(Helpで表示)                         */ 
0094:   }; 
0095:  
0096: /*----------------------------------------------------------------------------*/ 
0097: /* オプションをまとめる                                                       */ 
0098: /*----------------------------------------------------------------------------*/ 
0099: void *opt[]={&optENC,&optINF,&optOTF,&optZIP,NULL}; 
0100:  
0101: /*----------------------------------------------------------------------------*/ 
0102: /* 構造体                                                                     */ 
0103: /*----------------------------------------------------------------------------*/ 
0104: typedef struct _XmlState { 
0105:   int level; 
0106:   int crFlg; 
0107: } XmlState; 
0108:  
0109: /*----------------------------------------------------------------------------*/ 
0110: /* SAX ハンドラー                                                             */ 
0111: /*----------------------------------------------------------------------------*/ 
0112: void start_doc(XmlState *state){ 
0113:  
0114:   inEnc=mssStrdup((char *)ctxt->input->encoding); 
0115:   inVer=mssStrdup((char *)ctxt->version); 
0116:   mssWriteXmlDeclaration( inVer, optENC.str, fpw ); 
0117:  
0118:   /*出力のiconvオープン*/ 
0119:   icid=iconv_open(optENC.str,"UTF-8"); 
0120:   if((int)icid==-1) { 
0121:     mssShowErrMsg("encoding type error in iconv_open"); 
0122:     mssEnd(mssErrorNoDefault); 
0123:   } 
0124: } 
0125:  
0126: void end_doc(XmlState *state){ 
0127:  
0128:   if(icid!=NULL) iconv_close(icid); 
0129: } 
0130:  
0131:  
0132: /*エレメント start */ 
0133: void start_element(XmlState *state, char *fullname, char **atts){ 
0134:   struct mssXmlTag *xmlTag; 
0135:   int i; 
0136:  
0137:   mssGV.inCnt++; 
0138:   if(state->crFlg){ 
0139:     mssWriteRet(fpw); 
0140:     state->crFlg=0; 
0141:   } 
0142:  
0143:   mssWriteXmlIndent(state->level,fpw); 
0144:   xmlTag=mssInitXmlTag(fullname,NULL); 
0145:   if(atts!=NULL){ 
0146:     for(i=0;;i++){ 
0147:       if(*(atts+2*i+0)==NULL) break; 
0148:       if(*(atts+2*i+1)==NULL) break; 
0149:       mssAddXmlTagAttributeStr(xmlTag,*(atts+2*i),*(atts+2*i+1),NULL); 
0150:     } 
0151:   } 
0152:   mssWriteXmlStartTag(xmlTag,icid,fpw); 
0153:   mssFreeXmlTag(xmlTag); 
0154:  
0155:   mssGV.outCnt++; 
0156:   state->level++; 
0157: } 
0158:  
0159: /*エレメント end */ 
0160: void end_element(XmlState *state, char *fullname, char **atts){ 
0161:   struct mssXmlTag *xmlTag; 
0162:  
0163:   state->level--; 
0164:  
0165:   if(state->crFlg){ 
0166:     mssWriteRet(fpw); 
0167:     mssWriteXmlIndent(state->level,fpw); 
0168:     state->crFlg=0; 
0169:   } 
0170:  
0171:   xmlTag=mssInitXmlTag(fullname,NULL); 
0172:   mssWriteXmlEndTag(xmlTag,icid,fpw); 
0173:   mssFreeXmlTag(xmlTag); 
0174:  
0175:   if(state->level==0){ 
0176:     mssWriteRet(fpw); 
0177:   } 
0178: } 
0179:  
0180: void start_characters(XmlState *state, xmlChar *chars, int len){ 
0181:   char *tmp; 
0182:  
0183:   switch(*chars){ 
0184:   case '\n': 
0185:     state->crFlg=1; break; 
0186:   case '&': 
0187:     mssWriteStr("&amp;",fpw); break; 
0188:   case '>': 
0189:     mssWriteStr("&gt;",fpw); break; 
0190:   case '<': 
0191:     mssWriteStr("&lt;",fpw); break; 
0192:   case '\'': 
0193:     mssWriteStr("&apos;",fpw); break; 
0194:   case '"': 
0195:     mssWriteStr("&quot;",fpw); break; 
0196:   default: 
0197:     tmp=mssNencoding(chars,len,icid); 
0198:     mssWriteStr(tmp,fpw); 
0199:     mssFree(tmp); 
0200:   } 
0201: } 
0202:  
0203: /*sax error handler*/ 
0204: #include "saxerror.h" 
0205:  
0206: static xmlSAXHandler SAXFunctions = { 
0207:     NULL, /* internalSubset */ 
0208:     NULL, /* isStandalone */ 
0209:     NULL, /* hasInternalSubset */ 
0210:     NULL, /* hasExternalSubset */ 
0211:     NULL, /* resolveEntity */ 
0212:     NULL, /* getEntity */ 
0213:     NULL, /* entityDecl */ 
0214:     NULL, /* notationDecl */ 
0215:     NULL, /* attributeDecl */ 
0216:     NULL, /* elementDecl */ 
0217:     NULL, /* unparsedEntityDecl */ 
0218:     NULL, /* setDocumentLocator */ 
0219:     (startDocumentSAXFunc)start_doc, /* startDocument */ 
0220:     (endDocumentSAXFunc)end_doc, /* endDocument */ 
0221:     (startElementSAXFunc)start_element, /* startElement */ 
0222:     (endElementSAXFunc)end_element, /* endElement */ 
0223:     NULL, /* reference */ 
0224:     (charactersSAXFunc) start_characters, /* characters */ 
0225:     NULL, /* ignorableWhitespace */ 
0226:     NULL, /* processingInstruction */ 
0227:     NULL, /* comment */ 
0228:     (warningSAXFunc) xmlSaxErrEnd, /* xmlParserWarning */ 
0229:     (errorSAXFunc) xmlSaxErrEnd, /* xmlParserError */ 
0230:     (fatalErrorSAXFunc) xmlSaxErrEnd, /* xmlParserError */ 
0231:     NULL, /* getParameterEntity */ 
0232: }; 
0233:  
0234: int main(int argc, char *argv[]){ 
0235:  
0236:   XmlState         *state; 
0237:  
0238: /*----------------------------------------------------------------------------*/ 
0239: /* 前処理                                                                     */ 
0240: /*----------------------------------------------------------------------------*/ 
0241:   mssInit(argc,argv,&comHelp);        /* シグナル処理などの初期化     */ 
0242:   mssHelpDoc(opt,&comHelp,argc,argv); /* ヘルプ                       */ 
0243:   mssSetOption(opt,argc,argv);        /* コマンドオプションの設定     */ 
0244:  
0245:   fpw=mssOpenFPW(optOTF.str,optZIP.set,0); /*標準出力オープン*/ 
0246:  
0247: /*----------------------------------------------------------------------------*/ 
0248: /*メインルーチン                                                              */ 
0249: /*----------------------------------------------------------------------------*/ 
0250:  
0251:   state=mssCalloc(sizeof(XmlState),"xml2xt"); 
0252:  
0253:   if(optINF.set){ 
0254:     ctxt=(xmlParserCtxtPtr)xmlCreateFileParserCtxt(optINF.str); 
0255:   }else{ 
0256:     ctxt=(xmlParserCtxtPtr)xmlCreateFileParserCtxt("/dev/stdin"); 
0257:   } 
0258:   if(!ctxt){ 
0259:     mssShowErrMsg("not xml file\n"); 
0260:     mssEnd(mssErrorNoDefault); 
0261:   } 
0262:   ctxt->sax=&SAXFunctions; 
0263:  
0264:   ctxt->userData=state; 
0265:   xmlParseDocument(ctxt); 
0266:   ctxt->sax=NULL; 
0267:   xmlFreeParserCtxt(ctxt); 
0268:  
0269:   mssFree(inEnc); 
0270:   mssFree(inVer); 
0271:   mssFree(state); 
0272:  
0273: /*----------------------------------------------------------------------------*/ 
0274: /*フッター出力&終了処理                                                       */ 
0275: /*----------------------------------------------------------------------------*/ 
0276:   mssCloseFPW(fpw);     /*出力ファイルのクローズ      */ 
0277:   mssFreeOption(opt);   /*オプション領域開放          */ 
0278:   mssShowEndMsg();      /* 完了メッセージ             */ 
0279:   return(0);            /* to avoid warning message   */ 
0280: }