MUSASHI C source: xmlcat.c
0001: /*============================================================================*/
0002: /* 変更履歴 */
0003: /*----------------------------------------------------------------------------*/
0004: /* 1.0 : 新しいAPIに対応 */
0005: /*============================================================================*/
0006: #include <musashi.h>
0007: #include <stdio.h>
0008: #include <stdlib.h>
0009: #include <string.h>
0010: #include <libxml/parser.h>
0011: #include <libxml/parserInternals.h>
0012: #include <libxml/encoding.h>
0013: #include <iconv.h>
0014: #include <errno.h>
0015: #include <glob.h>
0016:
0017: #include <xmlcatHelp.h>
0018: struct mssComHelp comHelp={
0019: "xmlcat", /* コマンド名 */
0020: "1.0", /* バージョン */
0021: HELPT, /* コマンドタイトル */
0022: HELPS, /* 要約 */
0023: HELPE, /* 利用例 */
0024: HELPR, /* 参照コマンド */
0025: HELPA, /* 作者情報 */
0026: HELPB, /* バグレポート情報 */
0027: HELPH /* ホームページ */
0028: };
0029:
0030: #define UNDEF 0
0031: #define MAX_NEST 32
0032: #define LOCAL_BUF 256
0033: #define EncMax MssFieldMaxLen /*iconvで使う出力用文字列長*/
0034:
0035: /*----------------------------------------------------------------------------*/
0036: /* グローバル変数 */
0037: /*----------------------------------------------------------------------------*/
0038: extern xmlParserCtxtPtr ctxt;
0039: extern struct mssGlobalVariables mssGV;
0040:
0041: static struct mssFPW *fpw; /*出力ファイル構造体*/
0042: static iconv_t *icid;
0043: static char *inEnc1=NULL; /*一つ目のファイルのエンコーディング*/
0044: static char *inVer1=NULL; /*一つ目のファイルのバージョン*/
0045: static char *inEncN=NULL; /*二つ目以降のファイルのエンコーディング*/
0046: static char *inVerN=NULL; /*二つ目以降のファイルのバージョン*/
0047: static int procFileNo=-1;/*現在処理中のファイル番号(一つ目のファイルを認識するため)*/
0048: static struct mssXmlTag *rootTag;
0049:
0050: /*----------------------------------------------------------------------------*/
0051: /* ルートタグ名 */
0052: /*----------------------------------------------------------------------------*/
0053: MssOptSTR optRTG={
0054: OSTR, /* オプションタイプ */
0055: "R", /* キーワード(複数文字は不可) */
0056: 0, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0057: NULL , /* デフォルト */
0058: 1, /* 文字列の最小長 */
0059: 256, /* 文字列の最大長 */
0060: RTGT, /* このオプションのタイトル(Helpで表示) */
0061: RTGC /* このオプションのコメント(Helpで表示) */
0062: };
0063:
0064: /*----------------------------------------------------------------------------*/
0065: /* 入力ファイル */
0066: /*----------------------------------------------------------------------------*/
0067: MssOptINF optINF={
0068: OINF, /* オプションタイプ */
0069: "i", /* キーワード(複数文字は不可) */
0070: 0, /* 0:オプション, 1:必須 */
0071: 256, /* 指定可能の最大ファイル数 */
0072: 1, /*1:file not foundのエラーで終了しない 0:する */
0073: INFT, /* このオプションのタイトル(Helpで表示) */
0074: INFC /* このオプションのコメント(Helpで表示) */
0075: };
0076:
0077: /*----------------------------------------------------------------------------*/
0078: /* 出力ファイル */
0079: /*----------------------------------------------------------------------------*/
0080: MssOptOTF optOTF={
0081: OOTF, /* オプションタイプ */
0082: "o", /* キーワード(複数文字は不可) */
0083: 0, /* 0:オプション, 1:必須 */
0084: OTFT, /* このオプションのタイトル(Helpで表示) */
0085: OTFC /* このオプションのコメント(Helpで表示) */
0086: };
0087:
0088: /*----------------------------------------------------------------------------*/
0089: /* 圧縮出力 */
0090: /*----------------------------------------------------------------------------*/
0091: MssOptFLG optZIP={
0092: OFLG, /* オプションタイプ */
0093: "z", /* キーワード(複数文字は不可) */
0094: 0, /* デフォルト(基本的には0) 常にonにしたいときは1にする */
0095: ZIPT, /* このオプションのタイトル(Helpで表示) */
0096: ZIPC /* このオプションのコメント(Helpで表示) */
0097: };
0098:
0099: /*----------------------------------------------------------------------------*/
0100: /* オプションをまとめる */
0101: /*----------------------------------------------------------------------------*/
0102: void *opt[]={&optRTG,&optINF,&optOTF,&optZIP,NULL};
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: } XmlState;
0132:
0133: /*----------------------------------------------------------------------------*/
0134: /* SAX ハンドラー */
0135: /*----------------------------------------------------------------------------*/
0136: void start_doc(XmlState *state){
0137:
0138: procFileNo++; /*処理中のファイル番号をUP*/
0139:
0140: /*一つ目のファイルのXML宣言を獲得し出力*/
0141: if(procFileNo==0){
0142: inEnc1=mssStrdup((char *)ctxt->input->encoding);
0143: inVer1=mssStrdup((char *)ctxt->version);
0144: mssWriteXmlDeclaration( inVer1, inEnc1, fpw );
0145: if(inEnc1==NULL) inEnc1=mssStrdup("UTF-8");
0146:
0147: /*出力のiconvオープン*/
0148: icid=iconv_open(inEnc1,"UTF-8");
0149: if((int)icid==-1){
0150: mssShowErrMsg("encoding type error in iconv_open");
0151: mssEnd(mssErrorNoDefault);
0152: }
0153:
0154: /*二つ目以降のファイルのXML宣言を獲得し一つ目と比較*/
0155: }else{
0156: mssFree(inEncN);
0157: mssFree(inVerN);
0158: inEncN=mssStrdup((char *)ctxt->input->encoding);
0159: inVerN=mssStrdup((char *)ctxt->version);
0160: if(inEncN==NULL) inEncN=mssStrdup("UTF-8");
0161: if( 0!=strcmp(inVer1,inVerN) ){
0162: mssShowErrMsg("different xml version on %s",ctxt->input->filename);
0163: mssEnd(mssErrorNoDefault);
0164: }
0165: if( 0!=strcmp(inEnc1,inEncN) ){
0166: mssShowErrMsg("different xml encoding on %s",ctxt->input->filename);
0167: mssEnd(mssErrorNoDefault);
0168: }
0169: /*出力のiconvオープン*/
0170: icid=iconv_open(inEncN,"UTF-8");
0171: if((int)icid==-1){
0172: mssShowErrMsg("encoding type error in iconv_open");
0173: mssEnd(mssErrorNoDefault);
0174: }
0175: }
0176: }
0177:
0178: void end_doc(XmlState *state){
0179: if(icid!=NULL) iconv_close(icid);
0180: }
0181:
0182: /*エレメント start */
0183: void start_element(XmlState *state, char *fullname, char **atts){
0184:
0185: struct mssXmlTag *xmlTag;
0186: int i;
0187:
0188: mssGV.inCnt++;
0189:
0190: if(state->level==0){
0191: if(!optRTG.set){
0192: if(!procFileNo==0){
0193: if(0!=strcmp(rootTag->element,fullname)){
0194: mssShowErrMsg("different root tag [%s] in %s",
0195: fullname,ctxt->input->filename );
0196: mssEnd(mssErrorNoDefault);
0197: }
0198: state->level++;
0199: return;
0200: }else{
0201: rootTag=mssInitXmlTag(fullname,NULL);
0202: }
0203:
0204: /*ルートタグが指定されている*/
0205: }else{
0206: if(procFileNo==0){
0207: mssWriteXmlStartTag(rootTag,icid,fpw);
0208: mssGV.outCnt++;
0209: state->crFlg=1;
0210: state->level++;
0211: }
0212: }
0213: }
0214:
0215: if(state->crFlg){
0216: mssWriteRet(fpw);
0217: state->crFlg=0;
0218: }
0219: mssWriteXmlIndent(state->level,fpw);
0220:
0221: xmlTag=mssInitXmlTag(fullname,NULL);
0222: if(atts!=NULL){
0223: for(i=0;;i++){
0224: if(*(atts+2*i+0)==NULL) break;
0225: if(*(atts+2*i+1)==NULL) break;
0226: mssAddXmlTagAttributeStr(xmlTag,*(atts+2*i),*(atts+2*i+1),NULL);
0227: }
0228: }
0229: mssWriteXmlStartTag(xmlTag,icid,fpw);
0230: mssFreeXmlTag(xmlTag);
0231:
0232: mssGV.outCnt++;
0233: state->level++;
0234: }
0235:
0236: /*エレメント end */
0237: void end_element(XmlState *state, char *fullname, char **atts){
0238:
0239: struct mssXmlTag *xmlTag;
0240:
0241: state->level--;
0242:
0243: /* ルートタグ & add型 & 最後のファイルでない */
0244: if(state->level==0){
0245: if(!optRTG.set){
0246: if(procFileNo!=optINF.cnt-1){
0247: return;
0248: }
0249: }
0250: }
0251:
0252: if(state->crFlg){
0253: mssWriteRet(fpw);
0254: mssWriteXmlIndent(state->level,fpw);
0255: state->crFlg=0;
0256: }
0257: xmlTag=mssInitXmlTag(fullname,NULL);
0258: mssWriteXmlEndTag(xmlTag,icid,fpw);
0259: mssFreeXmlTag(xmlTag);
0260:
0261: if(optRTG.set){
0262: if(state->level==1){
0263: mssWriteRet(fpw);
0264: if(procFileNo==optINF.cnt-1){
0265: mssWriteXmlEndTag(rootTag,icid,fpw);
0266: mssWriteRet(fpw);
0267: state->level--;
0268: }
0269: }
0270: }else{
0271: if(state->level==0){
0272: mssWriteRet(fpw);
0273: }
0274: }
0275: }
0276:
0277: void start_characters(XmlState *state, xmlChar *chars, int len){
0278: char *tmp;
0279:
0280: switch(*chars){
0281: case '\n':
0282: state->crFlg=1; break;
0283: case '&':
0284: mssWriteStr("&",fpw); break;
0285: case '>':
0286: mssWriteStr(">",fpw); break;
0287: case '<':
0288: mssWriteStr("<",fpw); break;
0289: case '\'':
0290: mssWriteStr("'",fpw); break;
0291: case '"':
0292: mssWriteStr(""",fpw); break;
0293: default:
0294: tmp=mssNencoding(chars,len,icid);
0295: mssWriteStr(tmp,fpw);
0296: mssFree(tmp);
0297: }
0298: }
0299:
0300: void start_cdata(XmlState *state, xmlChar *chars, int len){
0301: char *tmp;
0302:
0303: mssWriteStr("<![CDATA[",fpw);
0304: tmp=mssNencoding(chars,len,icid);
0305: mssWriteStr(tmp,fpw);
0306: mssFree(tmp);
0307: mssWriteStr("]]>",fpw);
0308: }
0309:
0310: static xmlEntityPtr get_entity( XmlState *ctx, xmlChar *name){
0311: return xmlGetPredefinedEntity(name);
0312: }
0313:
0314: /*sax error handler*/
0315: #include "saxerror.h"
0316:
0317: static xmlSAXHandler SAXFunctions = {
0318: NULL, /* internalSubset */
0319: NULL, /* isStandalone */
0320: NULL, /* hasInternalSubset */
0321: NULL, /* hasExternalSubset */
0322: NULL, /* resolveEntity */
0323: (getEntitySAXFunc) get_entity, /* getEntity */
0324: NULL, /* entityDecl */
0325: NULL, /* notationDecl */
0326: NULL, /* attributeDecl */
0327: NULL, /* elementDecl */
0328: NULL, /* unparsedEntityDecl */
0329: NULL, /* setDocumentLocator */
0330: (startDocumentSAXFunc)start_doc, /* startDocument */
0331: (endDocumentSAXFunc)end_doc, /* endDocument */
0332: (startElementSAXFunc)start_element, /* startElement */
0333: (endElementSAXFunc)end_element, /* endElement */
0334: NULL, /* reference */
0335: (charactersSAXFunc) start_characters, /* characters */
0336: NULL, /* ignorableWhitespace */
0337: NULL, /* processingInstruction */
0338: NULL, /* comment */
0339: (warningSAXFunc) xmlSaxErrEnd, /* xmlParserWarning */
0340: (errorSAXFunc) xmlSaxErrEnd, /* xmlParserError */
0341: (fatalErrorSAXFunc) xmlSaxErrEnd, /* xmlParserError */
0342: NULL, /* getParameterEntity */
0343: (cdataBlockSAXFunc)start_cdata,
0344: };
0345:
0346: int main(int argc, char *argv[]){
0347:
0348: XmlState *state;
0349: int i;
0350:
0351: /*----------------------------------------------------------------------------*/
0352: /* 前処理 */
0353: /*----------------------------------------------------------------------------*/
0354: mssInit(argc,argv,&comHelp); /* シグナル処理などの初期化 */
0355: mssHelpDoc(opt,&comHelp,argc,argv); /* ヘルプ */
0356: mssSetOption(opt,argc,argv); /* コマンドオプションの設定 */
0357:
0358: /*引数のタグ名、属性名をUTF-8に変換して格納*/
0359: if(optRTG.set){
0360: icid=iconv_open("UTF-8",MssXmlDefEnc);
0361: if((int)icid==-1) {
0362: mssShowErrMsg("encoding type error in -E");
0363: mssEnd(mssErrorNoDefault);
0364: }
0365:
0366: rootTag=mssOpt2XmlTag(optRTG.str,icid);
0367: //rootTag=mssOpt2XmlTag(optRTG.str,NULL);
0368:
0369: if(icid!=NULL) iconv_close(icid);
0370: }
0371:
0372: /*標準出力オープン*/
0373: fpw=mssOpenFPW(optOTF.str,optZIP.set,0);
0374: //mssWriteXmlStartTag(rootTag,NULL,fpw);
0375:
0376: /*----------------------------------------------------------------------------*/
0377: /*メインルーチン */
0378: /*----------------------------------------------------------------------------*/
0379:
0380: state=mssCalloc(sizeof(XmlState),"xml2xt");
0381: for(i=0; i<optINF.cnt; i++){
0382:
0383: ctxt=(xmlParserCtxtPtr)xmlCreateFileParserCtxt(*(optINF.strList+i));
0384: if(!ctxt){
0385: mssShowErrMsg("not xml file");
0386: mssEnd(mssErrorNoDefault);
0387: }
0388: ctxt->sax=&SAXFunctions;
0389:
0390: ctxt->userData=state;
0391: xmlParseDocument(ctxt);
0392: ctxt->sax=NULL;
0393: xmlFreeParserCtxt(ctxt);
0394: }
0395:
0396: mssFree(inEnc1);
0397: mssFree(inVer1);
0398: mssFree(inEncN);
0399: mssFree(inVerN);
0400: mssFree(state);
0401: mssFreeXmlTag(rootTag);
0402:
0403: /*----------------------------------------------------------------------------*/
0404: /*フッター出力&終了処理 */
0405: /*----------------------------------------------------------------------------*/
0406: mssCloseFPW(fpw); /*出力ファイルのクローズ */
0407: mssFreeOption(opt); /*オプション領域開放 */
0408: mssShowEndMsg(); /*完了メッセージ */
0409: mssEnd(mssExitSuccess); /*終了 */
0410: return(0); /* to avoid warning message*/
0411: }