/* CXml2Txt by [HitU] team The program is intended to convert XML output from ADO Recordset.Save method. Produces tabulated text file, which is suitable for importing to MS Access/Excel. Last modified: 14.12.03 */ #include #include #include #include "xml2txt.h" class ADO_RecordSet : public CXml2Txt { protected: virtual void AnalyzeTag(tag &); // Tag analyzer private: list m_lTableHeader; // Column names }; void ADO_RecordSet::AnalyzeTag(tag &tTag) { static bool first_name = true; static unsigned long n_tags = 0, // Tag counter n_part = 0; // Part counter list::iterator column, iter; bool found; if( m_tags_per_part != 0 && n_tags == m_tags_per_part ) { string filename(m_sDst); // Start another part: n_part++; CXml2Txt::Close(DST); if( m_pause ) { printf("\nWaiting to create the next part.\nPress enter to continue..."); //getc(stdin); while( getc(stdin) != '\n' ) ; } // Form a filename: filename.insert(filename.rfind(".") == string::npos ? filename.length() : filename.rfind("."), "_part_" + to_string(n_part)); printf("\nCreating the next part: %s\n", filename.c_str()); if( (m_fout = fopen(filename.c_str(), "wb")) == NULL ) { sprintf(m_szError, "\nCan't create destination file part: %s\n", filename.c_str()); throw(Error(m_szError)); } // Create the table header: if( !m_lTableHeader.empty() ) { for( iter = m_lTableHeader.begin(); iter != m_lTableHeader.end(); ) { fprintf(m_fout, "%s", (*iter).c_str()); iter++; if( iter != m_lTableHeader.end() ) fprintf(m_fout, "%c", m_sep); } fprintf(m_fout, "\r\n"); } first_name = true; n_tags = 0; } // First output string should contain column names: if( tTag.sName == "s:AttributeType" ) { while( tTag.lAttribList.size() > 0 ) { if( tTag.lAttribList.front().sName == "name" ) { if( first_name ) { fprintf(m_fout, "%s", tTag.lAttribList.front().sValue.c_str()); first_name = false; } else fprintf(m_fout, "%c%s", m_sep, tTag.lAttribList.front().sValue.c_str()); m_lTableHeader.push_back(tTag.lAttribList.front().sValue); } tTag.lAttribList.pop_front(); } } // Columns description ends: if( tTag.sName == "/s:Schema" ) { fprintf(m_fout, "\r\n"); } // Save values: if( tTag.sName == "z:row" && !m_lTableHeader.empty()) { for(column = m_lTableHeader.begin(); column != m_lTableHeader.end() && tTag.lAttribList.size() > 0;) { // Check if we have this attribute in the table header: for( iter = m_lTableHeader.begin(), found = false; iter != m_lTableHeader.end(); iter++) { if( *iter == tTag.lAttribList.front().sName ) { found = true; break; } } if( !found ) { // Remove it from further processing: tTag.lAttribList.pop_front(); continue; } if( *column == tTag.lAttribList.front().sName ) { fprintf(m_fout, "%s", tTag.lAttribList.front().sValue.c_str()); tTag.lAttribList.pop_front(); } column++; if( column != m_lTableHeader.end() ) fprintf(m_fout, "%c", m_sep); } fprintf(m_fout, "\r\n"); n_tags++; } if( tTag.sName == "/xml") { printf("\nParsed \"\" tag."); } } /* --- Console version --- */ void BadArgs(const char *); void Usage(void); int main(int argc, char *argv[]) { CXml2Txt *RecordSet = new ADO_RecordSet; clock_t before; long double elapsed; char sep = '\t'; int arg; if( sizeof(fpos_t) < 8 ) { printf("Warning: fpos_t is only %d bytes long.\n", sizeof(fpos_t)); } if(argc == 1) { Usage(); return 0; } if(argc < 3) { BadArgs("argc < 3"); } while( (arg = getopt(argc, argv, "t:s:pv")) != -1) switch(arg) { case 't' : sep = optarg[0]; break; case 's' : unsigned long n_tags; sscanf(optarg, "%lu", &n_tags); RecordSet->SplitOutput(n_tags); break; case 'p' : RecordSet->SetPause(); break; case 'v' : RecordSet->BeVerbose(); break; case '?' : BadArgs("optarg"); break; default : BadArgs("optarg"); } if(argc != optind + 2 || argv[argc - 1] == NULL || argv[argc - 2] == NULL) { BadArgs("Source or destination files are not defined."); } if( strcmp(argv[argc - 1], argv[argc - 2]) == 0 ) { printf("\nOh no! I'm not going to work! ;)\n"); return 1; } try { before = clock(); RecordSet->Open(argv[argc - 2], argv[argc - 1]); printf("\nParsed %lu lines in ", RecordSet->Convert(sep)); RecordSet->Close(); elapsed = clock() - before; printf("%0.4Lf seconds.\n", elapsed / (long double)CLOCKS_PER_SEC); } catch(Error err) { printf("%s\n", err.m_str.c_str()); } catch(...) { printf("STL string/list exception."); } delete RecordSet; return 0; } void BadArgs(const char *err) { Usage(); printf("\nBad arguments (%s)\n", err); exit(1); } void Usage(void) { printf("\n"); printf("ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[v1.0]ÄÄ¿\n"); printf("³ Xml2Txt by HitU team ³\n"); printf("³ ³\n"); printf("³ - Converts ADO Recordset.Save output. ³\n"); printf("³ - Works with large(>4 gb) databases. ³\n"); printf("³ - Ability to split the output. ³\n"); printf("³ - Consumes a small amount of memory. ³\n"); printf("³ ³\n"); printf("ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[hitu.ussr.to]ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\n"); printf("\n"); printf("Usage: xml2txt [optional args] \n"); printf("Optional arguments:\n"); printf(" -t - set separator [Default: '\\t']\n"); printf(" -s - split output in N tags per file\n"); printf(" -p - pause after each part.\n"); printf(" -v - be more verbose\n"); } //