src/OdsHandler.h
branchv_0
changeset 2 3e73d4ae8b49
parent 0 2f3c9e508827
child 8 0ba80e9b711f
equal deleted inserted replaced
1:a8cb46dbb612 2:3e73d4ae8b49
    37 using namespace relpipe::reader;
    37 using namespace relpipe::reader;
    38 
    38 
    39 class OdsHandler : public handlers::RelationalReaderStringHadler {
    39 class OdsHandler : public handlers::RelationalReaderStringHadler {
    40 private:
    40 private:
    41 	std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // XML output will be always in UTF-8
    41 	std::wstring_convert<std::codecvt_utf8<wchar_t>> convertor; // XML output will be always in UTF-8
    42 	const char* INDENT = "\t";
    42 
       
    43 	// TODO: refactor and move common XML functions to relpipe-lib-xml
       
    44 	const char* INDENT_1 = "\t";
       
    45 	const char* INDENT_2 = "\t\t";
       
    46 	const char* INDENT_3 = "\t\t\t";
       
    47 	const char* INDENT_4 = "\t\t\t\t";
       
    48 	const char* INDENT_5 = "\t\t\t\t\t";
       
    49 	const char* INDENT_6 = "\t\t\t\t\t\t";
    43 
    50 
    44 	std::ostream &output;
    51 	std::ostream &output;
    45 
    52 
    46 	std::vector<TypeId> columnTypes;
    53 	std::vector<TypeId> columnTypes;
    47 	std::vector<string_t> columnTypeCodes;
    54 	std::vector<string_t> columnTypeCodes;
    48 	std::vector<string_t> columnNames;
    55 	std::vector<string_t> columnNames;
    49 	integer_t valueCount = 0;
    56 	integer_t valueCount = 0;
    50 	integer_t columnCount = 0;
    57 	integer_t columnCount = 0;
    51 	integer_t relationCount = 0;
    58 	integer_t relationCount = 0;
       
    59 
       
    60 	// TODO: refactor and move common XML functions to relpipe-lib-xml
    52 
    61 
    53 	const std::string escapeXmlText(const string_t &value) {
    62 	const std::string escapeXmlText(const string_t &value) {
    54 		std::wstringstream result;
    63 		std::wstringstream result;
    55 
    64 
    56 		for (auto & ch : value) {
    65 		for (auto & ch : value) {
    83 		valueCount = 0;
    92 		valueCount = 0;
    84 		columnCount = 0;
    93 		columnCount = 0;
    85 
    94 
    86 		if (relationCount == 0) {
    95 		if (relationCount == 0) {
    87 			output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
    96 			output << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
    88 			output << "<pipe TODO=\"ods\">" << std::endl;
    97 			output << "<office:document" << std::endl;
    89 			// TODO: xmlns
    98 			output << INDENT_1 << "xmlns:office=\"urn:oasis:names:tc:opendocument:xmlns:office:1.0\"" << std::endl;
       
    99 			output << INDENT_1 << "xmlns:table=\"urn:oasis:names:tc:opendocument:xmlns:table:1.0\"" << std::endl;
       
   100 			output << INDENT_1 << "xmlns:text=\"urn:oasis:names:tc:opendocument:xmlns:text:1.0\"" << std::endl;
       
   101 			output << INDENT_1 << "office:mimetype=\"application/vnd.oasis.opendocument.spreadsheet\"" << std::endl;
       
   102 			output << INDENT_1 << "office:version=\"1.2\">" << std::endl;
       
   103 
       
   104 			output << INDENT_1 << "<office:body>" << std::endl;
       
   105 			output << INDENT_2 << "<office:spreadsheet>" << std::endl;
       
   106 
    90 		} else {
   107 		} else {
    91 			output << INDENT << INDENT << "</record>" << std::endl;
   108 			output << INDENT_4 << "</table:table-row>" << std::endl;
    92 			output << INDENT << "</relation>" << std::endl;
   109 			output << INDENT_3 << "</table:table>" << std::endl;
    93 		}
   110 		}
    94 		relationCount++;
   111 		relationCount++;
    95 		output << INDENT << "<relation>" << std::endl;
   112 		// TODO: rename relations with same names
    96 
   113 		output << INDENT_3 << "<table:table table:name=\"" << escapeXmlText(name) << "\">" << std::endl;
    97 		output << INDENT << INDENT << "<name>" << escapeXmlText(name) << "</name>" << std::endl;
       
    98 
   114 
    99 
   115 
   100 		columnCount = attributes.size();
   116 		columnCount = attributes.size();
   101 		columnTypes.resize(columnCount);
   117 		columnTypes.resize(columnCount);
   102 		columnTypeCodes.resize(columnCount);
   118 		columnTypeCodes.resize(columnCount);
   103 		columnNames.resize(columnCount);
   119 		columnNames.resize(columnCount);
       
   120 
       
   121 		output << INDENT_4 << "<table:table-row>" << std::endl;
   104 		for (int i = 0; i < attributes.size(); i++) {
   122 		for (int i = 0; i < attributes.size(); i++) {
   105 			columnNames[i] = attributes[i].getAttributeName();
   123 			columnNames[i] = attributes[i].getAttributeName();
   106 			columnTypes[i] = attributes[i].getTypeId();
   124 			columnTypes[i] = attributes[i].getTypeId();
   107 			columnTypeCodes[i] = attributes[i].getTypeName();
   125 			columnTypeCodes[i] = attributes[i].getTypeName();
       
   126 
       
   127 			output << INDENT_5 << "<table:table-cell>" << std::endl;
       
   128 			output << INDENT_6 << "<text:p>";
       
   129 			output << escapeXmlText(columnNames[i]);
       
   130 			output << "</text:p>" << std::endl;
       
   131 			output << INDENT_5 << "</table:table-cell>" << std::endl;
   108 		}
   132 		}
   109 		
   133 		output << INDENT_4 << "</table:table-row>" << std::endl;
   110 		// TODO: print attribute metadata
   134 
   111 	}
   135 	}
   112 
   136 
   113 	void attribute(const string_t& value) override {
   137 	void attribute(const string_t& value) override {
   114 		integer_t i = valueCount % columnCount;
   138 		integer_t i = valueCount % columnCount;
   115 
   139 
   116 		if (i == 0 && valueCount) output << INDENT << INDENT << "</record>" << std::endl;
   140 		if (i == 0 && valueCount) output << INDENT_4 << "</table:table-row>" << std::endl;
   117 		if (i == 0) output << INDENT << INDENT << "<record>" << std::endl;
   141 		if (i == 0) output << INDENT_4 << "<table:table-row>" << std::endl;
   118 
   142 
   119 		valueCount++;
   143 		valueCount++;
   120 
   144 
   121 		// TODO: print attribute metadata (optional)
   145 		output << INDENT_5 << "<table:table-cell>" << std::endl;
   122 		output << INDENT << INDENT << INDENT << "<attribute>";
   146 		output << INDENT_6 << "<text:p>";
   123 		output << escapeXmlText(value);
   147 		output << escapeXmlText(value);
   124 		output << "</attribute>" << std::endl;
   148 		output << "</text:p>" << std::endl;
       
   149 		output << INDENT_5 << "</table:table-cell>" << std::endl;
   125 
   150 
   126 	}
   151 	}
   127 
   152 
   128 	void endOfPipe() {
   153 	void endOfPipe() {
   129 		if (valueCount) output << INDENT << INDENT << "</record>" << std::endl;
   154 		if (valueCount) output << INDENT_4 << "</table:table-row>" << std::endl;
   130 		if (relationCount) output << INDENT << "</relation>" << std::endl;
   155 		if (relationCount) output << INDENT_3 << "</table:table>" << std::endl;
   131 		output << "</pipe>" << std::endl;
   156 		output << INDENT_2 << "</office:spreadsheet>" << std::endl;
       
   157 		output << INDENT_1 << "</office:body>" << std::endl;
       
   158 		output << "</office:document>" << std::endl;
   132 
   159 
   133 	}
   160 	}
   134 
   161 
   135 };
   162 };
   136 
   163