MUSASHI C source: xml2xt.c
0001: /*============================================================================*/
0002: /* 変更履歴 */
0003: /*----------------------------------------------------------------------------*/
0004: /* 1.0 : 新しいAPIに対応(2003/06) */
0005: /* 1.1 : -Sを10文字まで指定可能にする */
0006: /*============================================================================*/
0007:
0008: #include <musashi.h>
0009: #include <stdio.h>
0010: #include <stdlib.h>
0011: #include <string.h>
0012: #include <ctype.h>
0013: #include <stdarg.h>
0014: #include <libxml/parser.h>
0015: #include <libxml/parserInternals.h>
0016: #include <libxml/encoding.h>
0017: #include <iconv.h>
0018: #include <errno.h>
0019: #include <regex.h>
0020:
0021: #include <xml2xtHelp.h>
0022: struct mssComHelp comHelp={
0023: "xml2xt", /* コマンド名 */
0024: "1.1", /* バージョン */
0025: HELPT, /* コマンドタイトル */
0026: HELPS, /* 要約 */
0027: HELPE, /* 利用例 */
0028: HELPR, /* 参照コマンド */
0029: HELPA, /* 作者情報 */
0030: HELPB, /* バグレポート情報 */
0031: HELPH /* ホームページ */
0032: };
0033:
0034: #define UNDEF 0
0035: #define MAX_NEST 32
0036: #define LOCAL_BUF 256
0037: #define EncMax MssFieldMaxLen /*iconvで使う出力用文字列長*/
0038:
0039: /*----------------------------------------------------------------------------*/
0040: /* 構造体 */
0041: /*----------------------------------------------------------------------------*/
0042:
0043: /* -f 項目名構造体 */
0044: /* ex) -f rec@id:recID */
0045: /* 要素パス@属性名%オプション:新項目名 */
0046: /* data/rec@id%f:recID,/a/b@id%n:keyID */
0047: /* eleNam[0][0]="data",[0][1]="rec",[0][2]=NULL */
0048: /* attNam[0]="id" */
0049: /* optNam[0][0]='f',[0][1]=0 */
0050: /* newNam[0]="recID" */
0051: /* */
0052: /* eleNam[1][0]="/",[1][1]="a",[1][2]="b",[1][3]=NULL */
0053: /* attNam[1]="id" */
0054: /* optNam[1][0]='f',[1][1]=0 */
0055: /* newNam[1]="keyID" */
0056:
0057: struct XmlFld {
0058: int cnt; /*項目数 */
0059: char *element[MssFieldMaxCnt]; /*要素名UTF8 */
0060: char *attribute[MssFieldMaxCnt]; /*属性名UTF8 */
0061: char option[MssFieldMaxCnt]; /*オプション t:テキスト,f:フラグ,n:名前 */
0062: char *field[MssFieldMaxCnt]; /*新項目名UTF8 */
0063: };
0064:
0065:
0066: struct XmlKey {
0067: char **path; /*-kで指定されたカンマで区切られた文字列*/
0068: regex_t *regex; /*上の文字列を正規表現にコンパイルしたもの*/
0069: int cnt; /*キー要素の数*/
0070: };
0071:
0072: typedef struct _XmlState {
0073: int level; /* 現在処理中の要素Nodeのレベル(rootNode=0) */
0074: }XmlState;
0075:
0076: /*----------------------------------------------------------------------------*/
0077: /* グローバル変数 */
0078: /*----------------------------------------------------------------------------*/
0079: extern xmlParserCtxtPtr ctxt;
0080: extern struct mssGlobalVariables mssGV;
0081:
0082: static struct mssFPW *fpw; /*出力ファイル構造体*/
0083: static struct mssHeader *hdo; /*出力ファイル用<head>タグ格納構造体*/
0084: static iconv_t *icid; /*iconv用 変換ハンドラ*/
0085: static char *inEnc=NULL; /*エンコーディング*/
0086: static char *inVer=NULL; /*バージョン*/
0087: static char currentPath[4096]; /*現在処理中のパス (/a/b/c/)*/
0088: static char *inKeyStartPath=NULL; /*-kで指定したパスからの現在処理中の相対パス*/
0089: static int inKey;/*現在処理中の要素が-kで指定したいずれかのパスに入ってるか*/
0090: static int inFldNo[MssFieldMaxCnt];/*現在処理中の-fの番号*/
0091: static char fldDat[MssFieldMaxCnt][MssFieldMaxLen];/*-fで指定された各項目の実際の値*/
0092: static struct XmlKey *key;
0093: static struct XmlFld *fld;
0094:
0095:
0096: /*============================================================================*/
0097: /* オプション宣言&定義 */
0098: /*============================================================================*/
0099: /*----------------------------------------------------------------------------*/
0100: /* 一行の単位となるXMLタグのパス名 */
0101: /*----------------------------------------------------------------------------*/
0102: MssOptSTR optKEY={
0103: OSTR, /* オプションタイプ */
0104: "k", /* キーワード(複数文字は不可) */
0105: 1, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0106: NULL, /* デフォルト */
0107: 1, /* 文字列の最小長 */
0108: 256, /* 文字列の最大長 */
0109: KEYT, /* このオプションのタイトル(Helpで表示) */
0110: KEYC /* このオプションのコメント(Helpで表示) */
0111: };
0112:
0113: /*----------------------------------------------------------------------------*/
0114: /* 出力する項目のタグ名 */
0115: /*----------------------------------------------------------------------------*/
0116: MssOptSTR optFLD={
0117: OSTR, /* オプションタイプ */
0118: "f", /* キーワード(複数文字は不可) */
0119: 1, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0120: NULL , /* デフォルト */
0121: 1, /* 文字列の最小長 */
0122: 1024, /* 文字列の最大長 */
0123: FLDT, /* このオプションのタイトル(Helpで表示) */
0124: FLDC /* このオプションのコメント(Helpで表示) */
0125: };
0126:
0127: /*----------------------------------------------------------------------------*/
0128: /* spaceを何に変換するか */
0129: /*----------------------------------------------------------------------------*/
0130: MssOptSTR optSPC={
0131: OSTR, /* オプションタイプ */
0132: "S", /* キーワード(複数文字は不可) */
0133: 0, /* 0:オプション, 1:必須, 2:XMLtableでのみ必須(txtでは無視) */
0134: "_", /* デフォルト */
0135: 0, /* 文字列の最小長 */
0136: 10, /* 文字列の最大長 */
0137: SPCT, /* このオプションのタイトル(Helpで表示) */
0138: SPCC /* このオプションのコメント(Helpで表示) */
0139: };
0140:
0141: /*----------------------------------------------------------------------------*/
0142: /* 入力ファイル */
0143: /*----------------------------------------------------------------------------*/
0144: MssOptINF optINF={
0145: OINF, /* オプションタイプ */
0146: "i", /* キーワード(複数文字は不可) */
0147: 0, /* 0:オプション, 1:必須 */
0148: 1, /* 指定可能の最大ファイル数 */
0149: 0, /*1:file not foundのエラーで終了しない 0:する */
0150: INFT, /* このオプションのタイトル(Helpで表示) */
0151: INFC /* このオプションのコメント(Helpで表示) */
0152: };
0153:
0154: /*----------------------------------------------------------------------------*/
0155: /* 出力ファイル */
0156: /*----------------------------------------------------------------------------*/
0157: MssOptOTF optOTF={
0158: OOTF, /* オプションタイプ */
0159: "o", /* キーワード(複数文字は不可) */
0160: 0, /* 0:オプション, 1:必須 */
0161: OTFT, /* このオプションのタイトル(Helpで表示) */
0162: OTFC /* このオプションのコメント(Helpで表示) */
0163: };
0164:
0165: /*----------------------------------------------------------------------------*/
0166: /* 圧縮出力 */
0167: /*----------------------------------------------------------------------------*/
0168: MssOptFLG optZIP={
0169: OFLG, /* オプションタイプ */
0170: "z", /* キーワード(複数文字は不可) */
0171: 0, /* デフォルト(基本的には0) 常にonにしたいときは1にする */
0172: ZIPT, /* このオプションのタイトル(Helpで表示) */
0173: ZIPC /* このオプションのコメント(Helpで表示) */
0174: };
0175:
0176: /*----------------------------------------------------------------------------*/
0177: /* オプションをまとめる */
0178: /*----------------------------------------------------------------------------*/
0179: void *opt[]={&optKEY,&optFLD,&optSPC,&optINF,&optOTF,&optZIP,NULL};
0180:
0181: /*----------------------------------------------------------------------------*/
0182: /* -k のトークン分割+encoding */
0183: /*----------------------------------------------------------------------------*/
0184: static void setXmlKey(void){
0185: int i;
0186: char *pos;
0187: char *keyPos[MssFieldMaxCnt];
0188:
0189: key=mssCalloc(sizeof(struct XmlKey),"setXmlKey");
0190: if(optKEY.set){
0191:
0192: /* カンマによるトークン分割 */
0193: i=0;
0194: pos = strtok(optKEY.str,",");
0195: while(pos!=NULL){
0196: keyPos[i++]=pos;
0197: pos=strtok(NULL,",");
0198: }
0199: key->cnt=i;
0200:
0201: /* encoding してpathにセット */
0202: key->path=mssCalloc(sizeof(char *),"xml2xt");
0203: for(i=0; i<key->cnt; i++){
0204: *(key->path+i)=mssEncoding(keyPos[i],icid);
0205: }
0206: }else{
0207: key->path=NULL;
0208: }
0209:
0210: key->regex=mssCalloc(sizeof(regex_t)*key->cnt,"xml2xt");
0211: for(i=0; i<key->cnt; i++){
0212: if( regcomp(key->regex+i,*(key->path+i),REG_EXTENDED) ){
0213: mssShowErrMsg("error in compiling regex");
0214: mssEnd(mssErrorNoDefault);
0215: }
0216: }
0217: }
0218:
0219: static void freeXmlKey(struct XmlKey *key){
0220: int i;
0221: if(key!=NULL){
0222: for(i=0; i<key->cnt; i++){
0223: if(*(key->path+i)!=NULL) mssFree(*(key->path+i));
0224: regfree(key->regex+i);
0225: }
0226: mssFree(key->regex);
0227: mssFree(key->path);
0228: mssFree(key);
0229: }
0230: }
0231:
0232: /*----------------------------------------------------------------------------*/
0233: /* -f のトークン分割+encoding */
0234: /* data/rec@id%f:recID,/a/b@id%n:keyID */
0235: /*----------------------------------------------------------------------------*/
0236: static struct XmlFld *setXmlFld(){
0237: int i,j;
0238: char *pos;
0239: struct XmlFld *fld=NULL;
0240: char *element[MssFieldMaxCnt]; /*encode前の要素名 */
0241: char *attribute[MssFieldMaxCnt]; /*encode前の属性名 */
0242: char option[MssFieldMaxCnt]; /*encode前のオプション */
0243: char *field[MssFieldMaxCnt]; /*encode前の新項目名 */
0244: char tmp[4096];
0245:
0246: fld=mssCalloc(sizeof(struct XmlFld),"setXmlFld");
0247:
0248: /*カンマのトークン分割(要素名の先頭アドレスをセット)*/
0249: /* data/rec@id%f:recID|/a/b@id%n:keyID */
0250: fld->cnt=0;
0251: pos = strtok(optFLD.str,",");
0252: while(pos!=NULL){
0253: if(fld->cnt>=MssFieldMaxCnt){
0254: mssShowErrMsg("too many fields on -f");
0255: mssEnd(mssErrorNoDefault);
0256:
0257: }
0258: element[fld->cnt]=pos;
0259: fld->cnt++;
0260: pos=strtok(NULL,",");
0261: }
0262:
0263: /*コロンでトークン分割(新項目名のセット:strdup)*/
0264: /* data/rec@id%f|recID|/a/b@id%n|keyID */
0265: for(i=0; i<fld->cnt; i++){
0266: pos=strchr(element[i],':');
0267: if(pos!=NULL){
0268: *pos='\0';
0269: field[i]=mssStrdup(++pos);
0270: }else{
0271: field[i]=NULL;
0272: }
0273: }
0274:
0275: /*%でトークン分割(オプションのセット) */
0276: /* data/rec@id|f|recID|/a/b@id|n|keyID */
0277: for(i=0; i<fld->cnt; i++){
0278: j=0;
0279: pos = strchr(element[i],'%');
0280: if(pos!=NULL){
0281: *pos='\0';
0282: option[i]=*(++pos);
0283: }else{
0284: option[i]=0;
0285: }
0286: }
0287:
0288: /*この段階で新項目名が指定されていなければ、
0289: 要素名+属性名を新項目名として登録する*/
0290: for(i=0; i<fld->cnt; i++){
0291: if(field[i]==NULL){
0292: field[i]=mssStrdup(element[i]);
0293: }
0294: }
0295:
0296: /*@でトークン分割(属性名のセット)*/
0297: /* data/rec|id|f|recID|/a/b|id|n|keyID */
0298: for(i=0; i<fld->cnt; i++){
0299: pos=strchr(element[i],'@');
0300: if(pos!=NULL){
0301: *pos='\0';
0302: attribute[i]=++pos;
0303: }else{
0304: attribute[i]=NULL;
0305: }
0306: }
0307:
0308: /*-----------------------------------*/
0309: /*UTF8へのencoding + 構造体へのセット*/
0310: /*-----------------------------------*/
0311: for(i=0; i<fld->cnt; i++){
0312:
0313: /*要素*/
0314: /* 要素の最後に"/"を加える */
0315: if(*(element[i]+strlen(element[i])-1)!='/'){
0316: strcpy(tmp,element[i]);
0317: strcat(tmp,"/");
0318: }else{
0319: strcpy(tmp,element[i]);
0320: }
0321: fld->element[i]=mssEncoding(tmp,icid);
0322:
0323: /*属性*/
0324: fld->attribute[i]=mssEncoding(attribute[i],icid);
0325:
0326: /*パラメータ*/
0327: fld->option[i]=option[i];
0328:
0329: /*新項目名*/
0330: fld->field[i]=mssEncoding(field[i],icid);
0331: }
0332:
0333: for(i=0; i<fld->cnt; i++){
0334: mssFree(field[i]);
0335: }
0336:
0337: return(fld);
0338: }
0339:
0340: static void freeXmlFld(struct XmlFld *fld){
0341: int i;
0342:
0343: for(i=0; i<fld->cnt; i++){
0344: if(fld->element[i] !=NULL) mssFree(fld->element[i]);
0345: if(fld->attribute[i]!=NULL) mssFree(fld->attribute[i]);
0346: if(fld->field[i] !=NULL) mssFree(fld->field[i]);
0347: }
0348: if(fld!=NULL)mssFree(fld);
0349: }
0350:
0351: static void writeEncStr(char *str){
0352: char *buf;
0353:
0354: if( str!=NULL && *str!='\0') {
0355: buf=mssEncoding(str,icid);
0356: mssWriteStr(buf,fpw);
0357: if(buf!=NULL && buf!=str) mssFree(buf);
0358: }else{
0359: mssWriteStr("*",fpw);
0360: }
0361: }
0362:
0363: /*左右のスペースを省き、途中のスペースを指定の文字列に変換する*/
0364: static char *chgSpc(char *str){
0365: int repStrLen;
0366: int cnt;
0367: char *pos;
0368: char *last;
0369: char *newStr; /*スペースを変換して保存する文字列領域*/
0370: char *retStr; /*返値用の文字列*/
0371:
0372: if(str==NULL) return(NULL);
0373:
0374: newStr=mssMalloc(sizeof(char)*(MssFieldMaxLen+1),"chgSpc");
0375: *newStr='\0';
0376:
0377: repStrLen=strlen(optSPC.str);
0378:
0379: /*左のスペース文字をスキップ*/
0380: while(*str!='\0'){
0381: if(!isspace(*str)) break;
0382: str++;
0383: }
0384:
0385: /*右のスペース文字を省く*/
0386: last=str+strlen(str)-1;
0387: if(str==last+1) return(newStr);
0388: while(*last==' '){
0389: if(!isspace(*last)) break;
0390: *last--='\0';
0391: }
0392:
0393: cnt=0;
0394: pos=newStr;
0395: while(*str!='\0'){
0396: if(*str==' '){
0397: /*項目最大長を超えたらそこで打ち切り*/
0398: if(cnt+repStrLen>=MssFieldMaxLen-1){
0399: break;
0400: }
0401: strncpy(pos,optSPC.str,repStrLen);
0402: pos+=repStrLen;
0403: str++;
0404: cnt+=repStrLen;
0405: }else{
0406: *pos++=*str++;
0407: cnt++;
0408: }
0409: }
0410: *pos='\0';
0411:
0412: retStr=mssStrdup(newStr);
0413: mssFree(newStr);
0414: return(retStr);
0415: }
0416:
0417: /*fldDatを出力*/
0418: static void printDat(XmlState *state){
0419: int fn;
0420: char *str;
0421:
0422: for(fn=0; fn<fld->cnt-1; fn++){
0423: str=chgSpc(fldDat[fn]);
0424: writeEncStr(str);
0425: mssFree(str);
0426: mssWriteDlm(fpw);
0427: }
0428: str=chgSpc(fldDat[fn]);
0429: writeEncStr(str);
0430: mssFree(str);
0431: mssWriteRet(fpw);
0432: mssGV.outCnt++;
0433: }
0434:
0435: /*fldDatをクリア*/
0436: static void clearFldDat(XmlState *state){
0437: int i;
0438:
0439: for(i=0; i<fld->cnt; i++){
0440: /*絶対パス指定(キー要素)の項目はクリアしない*/
0441: if(*fld->element[i]!='/') fldDat[i][0]='\0';
0442: }
0443: }
0444:
0445: void Strncpy(char *to, char *from, int len){
0446: int i,j;
0447:
0448: i=0;
0449: for(j=0; j<len; j++){
0450: *(to+i)=*(from+j);
0451: if((++i)>=MssFieldMaxLen-1) {
0452: mssShowErrMsg("exceed maximum length of field");
0453: mssEnd(mssErrorNoDefault);
0454: }
0455: }
0456: *(to+i)='\0';
0457: }
0458:
0459: void Strncat(char *to, char *from, int len){
0460: int i,j;
0461:
0462: i=strlen(to);
0463: for(j=0; j<len; j++){
0464: *(to+i)=*(from+j);
0465: if((++i)>=MssFieldMaxLen-1) {
0466: mssShowErrMsg("exceed maximum length of field");
0467: mssEnd(mssErrorNoDefault);
0468: }
0469: }
0470: *(to+i)='\0';
0471: }
0472:
0473: /*----------------------------------------------------------------------------*/
0474: /* SAX ハンドラー */
0475: /*----------------------------------------------------------------------------*/
0476: /*############## start_doc */
0477: void start_doc(XmlState *state){
0478: int i;
0479:
0480: inEnc=mssStrdup((char *)ctxt->input->encoding);
0481: inVer=mssStrdup((char *)ctxt->version);
0482: if(inEnc==NULL) inEnc=mssStrdup("UTF-8");
0483:
0484: /*パラメータ用のiconvオープン */
0485: /*xmlコマンドのパラメータ、入力データ、出力データのencoding */
0486: /*は全て、入力データのエンコーディングとおなじことを前提に作る。*/
0487: icid=iconv_open("UTF-8",inEnc);
0488: if((int)icid==-1) {
0489: mssShowErrMsg("encoding type error in iconv_open");
0490: mssEnd(mssErrorNoDefault);
0491: }
0492:
0493: /* -k,-f パラメータのセット+漢字をUTF-8に変換 */
0494: setXmlKey();
0495: fld=setXmlFld(key);
0496:
0497: /*パラメータ用のiconvクローズ*/
0498: if(icid!=NULL) iconv_close(icid);
0499:
0500: /*出力のiconvオープン*/
0501: icid=iconv_open(inEnc,"UTF-8");
0502: if((int)icid==-1) {
0503: mssShowErrMsg("encoding type error in iconv_open");
0504: mssEnd(mssErrorNoDefault);
0505: }
0506:
0507: /*出力ヘッダーの作成と出力 */
0508: hdo=mssInitHeader(NULL,NULL);
0509: for(i=0; i<fld->cnt; i++){
0510: mssAddFieldsByStr( hdo->flds, mssEncoding(fld->field[i],icid) );
0511: }
0512:
0513: /*xmlTableヘッダーの書き出し*/
0514: mssWriteHeader(hdo, fpw);
0515:
0516: /* currentPathの初期化 */
0517: currentPath[0]='/';
0518: currentPath[1]='\0';
0519:
0520: for(i=0; i<fld->cnt; i++){
0521: inFldNo[i]=0;
0522: }
0523: }
0524:
0525: /*############## end_doc */
0526: void end_doc(XmlState *state){
0527: /*出力用のiconvクローズ*/
0528: if(icid!=NULL) iconv_close(icid);
0529: }
0530:
0531: /*-kのキーに入ったならば1を返す。その他は0。*/
0532: static int isInKey(void){
0533: int i;
0534: for(i=0; i<key->cnt; i++){
0535: /*0でマッチ*/
0536: if(0==regexec(key->regex+i,currentPath,0,NULL,0)) return(1);
0537: }
0538: return(0);
0539: }
0540:
0541: /*----------------------------------------------*/
0542: /*-fの要素に入ったならば、その要素の番号を返す。*/
0543: /* inFldNo[]に当てはまる項目番号をセットし、 */
0544: /* inFldCntにその項目数をセットする。 */
0545: /*----------------------------------------------*/
0546: static void setInFld(){
0547: int i;
0548:
0549: for(i=0; i<fld->cnt; i++){
0550: if(*fld->element[i]=='/'){ /* ----- 絶対パスの場合 ( -f /a/b ) */
0551: if(currentPath!=NULL){
0552: if(0==strcmp(currentPath,fld->element[i])){
0553: inFldNo[i]=1;
0554: }
0555: }
0556: }else{ /* ----- 相対パスの場合 ( -f a/b ) */
0557: if(inKeyStartPath!=NULL){
0558: if(0==strcmp(inKeyStartPath,fld->element[i])){
0559: inFldNo[i]=1;
0560: }
0561: }
0562: }
0563: }
0564: }
0565:
0566: static void unsetInFld(){
0567: int i;
0568:
0569: for(i=0; i<fld->cnt; i++){
0570: if(*fld->element[i]=='/'){ /* ----- 絶対パスの場合 ( -f /a/b ) */
0571: if(currentPath!=NULL){
0572: if(0==strcmp(currentPath,fld->element[i])){
0573: inFldNo[i]=0;
0574: }
0575: }
0576: }else{ /* ----- 相対パスの場合 ( -f a/b ) */
0577: if(inKeyStartPath!=NULL){
0578: if(0==strcmp(inKeyStartPath,fld->element[i])){
0579: inFldNo[i]=0;
0580: }
0581: }
0582: }
0583: }
0584: }
0585:
0586: static char *getAttVal(char *attName, char **atts) {
0587: int i;
0588:
0589: if(atts==NULL || attName==NULL) return(NULL);
0590:
0591: i=0;
0592: while(1){
0593: if( *(atts+i)==NULL ) return(NULL);
0594: if( 0==strcmp(attName,*(atts+i)) ){
0595: return(*(atts+i+1));
0596: }
0597: i=i+2;
0598: }
0599: }
0600:
0601: /*############## start_element */
0602: void start_element(XmlState *state, char *fullname, char **atts){
0603: char *attVal;
0604: int prvInKey=inKey;
0605:
0606: int i;
0607:
0608: mssGV.inCnt++;
0609:
0610: /*現在のノードパスを更新*/
0611: strcat(currentPath,fullname);
0612: strcat(currentPath,"/");
0613:
0614: /*-kのキーに入ったかどうか*/
0615: inKey=isInKey();
0616:
0617: /*初めてキーに入った場合 キー内の開始文字位置をセット*/
0618: if(prvInKey==0 && inKey==1){
0619: inKeyStartPath=currentPath+strlen(currentPath);
0620: }
0621:
0622: /*-fで指定したどの要素に入っているか*/
0623: setInFld();
0624:
0625: for(i=0; i<fld->cnt; i++){
0626: if(inFldNo[i]){
0627: /*属性指定項目の場合(<a id="aaa">)*/
0628: if(fld->attribute[i]!=NULL){
0629: attVal=getAttVal(fld->attribute[i],atts);
0630: if( attVal!=NULL ){
0631: switch(fld->option[i]){
0632: case 'f': /*フラグ*/
0633: fldDat[i][0]='1';
0634: fldDat[i][1]='\0';
0635: break;
0636: case 'n': /*名前(要素名+属性名)*/
0637: Strncpy(fldDat[i],currentPath,strlen(currentPath));
0638: fldDat[i][strlen(currentPath)-1]='\0'; /*最後の"/"を消す*/
0639: Strncat(fldDat[i],"@",1);
0640: Strncat(fldDat[i],fld->attribute[i],strlen(fld->attribute[i]));
0641: break;
0642: default: /*テキスト(デフォルト)*/
0643: Strncpy(fldDat[i],attVal,strlen(attVal));
0644: break;
0645: }
0646: }
0647:
0648: /*要素指定項目の場合(<a>)*/
0649: }else{
0650: switch(fld->option[i]){
0651: case 'f': /*フラグ*/
0652: fldDat[i][0]='1';
0653: fldDat[i][1]='\0';
0654: break;
0655: case 'n': /*名前(要素名+属性名)*/
0656: Strncpy(fldDat[i],currentPath,strlen(currentPath));
0657: fldDat[i][strlen(currentPath)-1]='\0'; /*最後の"/"を消す*/
0658: break;
0659: default: /*テキスト(デフォルト)*/
0660: /*要素内テキスト指定の場合(<a>text</a>)はcharacerにてセットする*/
0661: /*同じ要素が出て来たときのために、前のデータをクリアする*/
0662: fldDat[i][0]='\0'; /*最後の"/"を消す*/
0663: break;
0664: }
0665: }
0666: }
0667: }
0668: state->level++;
0669: }
0670:
0671: /*############## end_element */
0672: void end_element(XmlState *state, char *fullname, char **atts){
0673: int prvInKey=inKey;
0674: char *pos;
0675:
0676: unsetInFld();
0677:
0678: state->level--;
0679:
0680: /*現在のノードパスを更新*/
0681: pos=currentPath+strlen(currentPath)-2;
0682: while(*pos!='/') pos--;
0683: *(++pos)='\0';
0684:
0685: /*今回のend_elementでキーを出たならば*/
0686: inKey=isInKey();
0687: if(prvInKey==1 && inKey==0){
0688: /*キーから出る場合 キー内の開始文字位置をNULLにセット*/
0689: inKeyStartPath=NULL;
0690: /*データ出力*/
0691: printDat(state);
0692: clearFldDat(state);
0693: }
0694:
0695: /*-fで指定したどの要素に入っているか*/
0696: /*end_elementでは、テキスト指定項目の時のみ、調査する*/
0697:
0698: }
0699:
0700: /*############## start_characters */
0701: void start_characters(XmlState *state, xmlChar *chars, int len){
0702: int i;
0703:
0704: for(i=0; i<fld->cnt; i++){
0705: if(inFldNo[i]){
0706: /*属性でなく、要素の場合*/
0707: if(fld->attribute[i]==NULL){
0708: /*%n,%fでない場合*/
0709: if(fld->option[i]==0){
0710: /* fldDat[i][0]='\0'; start_elementでクリアに変更*/
0711: Strncat(fldDat[i],chars,len);
0712: }
0713: }
0714: }
0715: }
0716: }
0717:
0718: /*sax error handler*/
0719: #include "saxerror.h"
0720:
0721: void xmlSaxErrEndLocal(void *ctx, const char *msg, ...){
0722:
0723: XmlState *dummy=NULL;
0724:
0725: if(0==strncmp(msg,"Document is empty",17)){
0726:
0727: ctxt->input->encoding=MssXmlDefEnc;
0728: start_doc(dummy);
0729: mssWriteFooter(fpw);
0730: mssCloseFPW(fpw);
0731: mssShowEndMsg();
0732: mssEnd(mssExitSuccess);
0733: }else{
0734: xmlSaxErrEnd(ctx, msg);
0735: }
0736: }
0737:
0738:
0739: static xmlSAXHandler SAXFunctions = {
0740: NULL, /* internalSubset */
0741: NULL, /* isStandalone */
0742: NULL, /* hasInternalSubset */
0743: NULL, /* hasExternalSubset */
0744: NULL, /* resolveEntity */
0745: NULL, /* getEntity */
0746: NULL, /* entityDecl */
0747: NULL, /* notationDecl */
0748: NULL, /* attributeDecl */
0749: NULL, /* elementDecl */
0750: NULL, /* unparsedEntityDecl */
0751: NULL, /* setDocumentLocator */
0752: (startDocumentSAXFunc)start_doc, /* startDocument */
0753: (endDocumentSAXFunc)end_doc, /* endDocument */
0754: (startElementSAXFunc)start_element, /* startElement */
0755: (endElementSAXFunc)end_element, /* endElement */
0756: NULL, /* reference */
0757: (charactersSAXFunc) start_characters, /* characters */
0758: NULL, /* ignorableWhitespace */
0759: NULL, /* processingInstruction */
0760: NULL, /* comment */
0761: (warningSAXFunc) xmlSaxErrEndLocal, /* xmlParserWarning */
0762: (errorSAXFunc) xmlSaxErrEndLocal, /* xmlParserError */
0763: (fatalErrorSAXFunc) xmlSaxErrEndLocal, /* xmlParserError */
0764: NULL, /* getParameterEntity */
0765: NULL,
0766: };
0767:
0768:
0769: int main(int argc, char *argv[]){
0770:
0771: XmlState *state;
0772:
0773: char *tmp;
0774: char *fname;
0775:
0776: /*----------------------------------------------------------------------------*/
0777: /* 前処理 */
0778: /*----------------------------------------------------------------------------*/
0779: mssInit(argc,argv,&comHelp); /* シグナル処理などの初期化 */
0780: mssHelpDoc(opt,&comHelp,argc,argv);/* ヘルプ */
0781: mssSetOption(opt,argc,argv); /* コマンドオプションの設定 */
0782:
0783: /*prnOption(opt);*/
0784:
0785: tmp=optSPC.str;
0786: while(*tmp!='\0'){
0787: if(isspace(*tmp++)) {
0788: mssShowErrMsg("cannot use space character in -S option");
0789: mssEnd(mssErrorNoDefault);
0790: }
0791: }
0792:
0793: fpw=mssOpenFPW(optOTF.str,optZIP.set,0); /*標準出力オープン*/
0794:
0795: /*----------------------------------------------------------------------------*/
0796: /*メインルーチン */
0797: /*----------------------------------------------------------------------------*/
0798: state=mssCalloc(sizeof(XmlState),"xml2xt");
0799: state->level = 0;
0800:
0801: if(optINF.set){
0802: fname=optINF.str;
0803: }else{
0804: fname="/dev/stdin";
0805: }
0806:
0807: ctxt=(xmlParserCtxtPtr)xmlCreateFileParserCtxt(fname);
0808: if(!ctxt){
0809: fprintf(stderr,"not xml\n");
0810: }
0811: ctxt->sax=&SAXFunctions;
0812: ctxt->userData=state;
0813: xmlParseDocument(ctxt);
0814: ctxt->sax=NULL;
0815: xmlFreeParserCtxt(ctxt);
0816:
0817: freeXmlKey(key);
0818: freeXmlFld(fld);
0819: mssFree(state);
0820:
0821: /*----------------------------------------------------------------------------*/
0822: /*フッター出力&終了処理 */
0823: /*----------------------------------------------------------------------------*/
0824: mssWriteFooter(fpw); /*フッターの出力*/
0825: mssCloseFPW(fpw); /*出力ファイルのクローズ*/
0826: mssFreeHeader(hdo); /*出力ヘッダ領域開放*/
0827: mssFreeOption(opt); /*オプション領域開放*/
0828: mssShowEndMsg(); /*完了メッセージ*/
0829: mssEnd(mssExitSuccess); /*終了*/
0830: return(0); /* to avoid warning message*/
0831: }