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("&",fpw); break;
0255: case '>':
0256: mssWriteStr(">",fpw); break;
0257: case '<':
0258: mssWriteStr("<",fpw); break;
0259: case '\'':
0260: mssWriteStr("'",fpw); break;
0261: case '"':
0262: mssWriteStr(""",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: }