# HG changeset patch # User František Kučera # Date 1546809338 -3600 # Node ID 0ba80e9b711fd0836fea71a46a1581ee1319bb49 # Parent b99b1debb00c5a14a02861a9cbbd63e9e5b03a44 move common XML code to relpipe-lib-xmlwriter (a header-only library) diff -r b99b1debb00c -r 0ba80e9b711f nbproject/configurations.xml --- a/nbproject/configurations.xml Thu Dec 20 00:26:00 2018 +0100 +++ b/nbproject/configurations.xml Sun Jan 06 22:15:38 2019 +0100 @@ -80,6 +80,7 @@ ../relpipe-lib-reader.cpp/include ../relpipe-lib-cli.cpp/include + ../relpipe-lib-xmlwriter.cpp/include build/Debug/src diff -r b99b1debb00c -r 0ba80e9b711f src/CMakeLists.txt --- a/src/CMakeLists.txt Thu Dec 20 00:26:00 2018 +0100 +++ b/src/CMakeLists.txt Sun Jan 06 22:15:38 2019 +0100 @@ -18,7 +18,7 @@ # Relpipe libraries: INCLUDE(FindPkgConfig) -pkg_check_modules (RELPIPE_LIBS relpipe-lib-reader.cpp relpipe-lib-cli.cpp) +pkg_check_modules (RELPIPE_LIBS relpipe-lib-reader.cpp relpipe-lib-cli.cpp relpipe-lib-xmlwriter.cpp) include_directories(${RELPIPE_LIBS_INCLUDE_DIRS}) link_directories(${RELPIPE_LIBS_LIBRARY_DIRS}) diff -r b99b1debb00c -r 0ba80e9b711f src/OdsHandler.h --- a/src/OdsHandler.h Thu Dec 20 00:26:00 2018 +0100 +++ b/src/OdsHandler.h Sun Jan 06 22:15:38 2019 +0100 @@ -29,27 +29,18 @@ #include #include #include +#include namespace relpipe { namespace out { namespace ods { using namespace relpipe::reader; +using namespace relpipe::xmlwriter; class OdsHandler : public handlers::RelationalReaderStringHadler { private: - std::wstring_convert> convertor; // XML output will be always in UTF-8 - - // TODO: refactor and move common XML functions to relpipe-lib-xml - const char* INDENT_1 = "\t"; - const char* INDENT_2 = "\t\t"; - const char* INDENT_3 = "\t\t\t"; - const char* INDENT_4 = "\t\t\t\t"; - const char* INDENT_5 = "\t\t\t\t\t"; - const char* INDENT_6 = "\t\t\t\t\t\t"; - - std::ostream &output; - + shared_ptr xmlWriter; std::vector columnTypes; std::vector columnTypeCodes; std::vector columnNames; @@ -57,60 +48,33 @@ integer_t columnCount = 0; integer_t relationCount = 0; - // TODO: refactor and move common XML functions to relpipe-lib-xml - - const std::string escapeXmlText(const string_t &value) { - std::wstringstream result; - - for (auto & ch : value) { - switch (ch) { - case L'&': result << L"&"; - break; - case L'<': result << L"<"; - break; - case L'>': result << L">"; - break; - case L'\'': result << L"'"; // TODO: escape ' and " only in attributes - break; - case L'"': result << L"""; // TODO: escape ' and " only in attributes - break; - default: result << ch; - } - } - - return convertor.to_bytes(result.str()); - } - public: - OdsHandler(std::ostream& output) : output(output) { + OdsHandler(std::ostream& output) : xmlWriter(new XMLWriter(output)) { } void startRelation(string_t name, std::vector attributes) override { - // TODO: refactor and move common XML functions to relpipe-lib-xml - valueCount = 0; columnCount = 0; if (relationCount == 0) { - output << "" << std::endl; - output << "" << std::endl; + xmlWriter->writeStartElement(L"office:document",{ + L"xmlns:office", L"urn:oasis:names:tc:opendocument:xmlns:office:1.0", + L"xmlns:table", L"urn:oasis:names:tc:opendocument:xmlns:table:1.0", + L"xmlns:text", L"urn:oasis:names:tc:opendocument:xmlns:text:1.0", + L"office:mimetype", L"application/vnd.oasis.opendocument.spreadsheet", + L"office:version", L"1.2" + }); - output << INDENT_1 << "" << std::endl; - output << INDENT_2 << "" << std::endl; - + xmlWriter->writeStartElement(L"office:body"); + xmlWriter->writeStartElement(L"office:spreadsheet"); } else { - output << INDENT_4 << "" << std::endl; - output << INDENT_3 << "" << std::endl; + xmlWriter->writeEndElement(); + xmlWriter->writeEndElement(); } relationCount++; // TODO: rename relations with same names - output << INDENT_3 << "" << std::endl; + xmlWriter->writeStartElement(L"table:table",{L"table:name", name}); columnCount = attributes.size(); @@ -118,44 +82,39 @@ columnTypeCodes.resize(columnCount); columnNames.resize(columnCount); - output << INDENT_4 << "" << std::endl; + xmlWriter->writeStartElement(L"table:table-row"); for (int i = 0; i < attributes.size(); i++) { columnNames[i] = attributes[i].getAttributeName(); columnTypes[i] = attributes[i].getTypeId(); columnTypeCodes[i] = attributes[i].getTypeName(); - output << INDENT_5 << "" << std::endl; - output << INDENT_6 << ""; - output << escapeXmlText(columnNames[i]); - output << "" << std::endl; - output << INDENT_5 << "" << std::endl; + xmlWriter->writeStartElement(L"table:table-cell"); + xmlWriter->writeTextElement(L"text:p",{}, columnNames[i]); + xmlWriter->writeEndElement(); } - output << INDENT_4 << "" << std::endl; + xmlWriter->writeEndElement(); } void attribute(const string_t& value) override { integer_t i = valueCount % columnCount; - if (i == 0 && valueCount) output << INDENT_4 << "" << std::endl; - if (i == 0) output << INDENT_4 << "" << std::endl; + if (i == 0 && valueCount) xmlWriter->writeEndElement(); + if (i == 0) xmlWriter->writeStartElement(L"table:table-row"); valueCount++; - output << INDENT_5 << "" << std::endl; - output << INDENT_6 << ""; - output << escapeXmlText(value); - output << "" << std::endl; - output << INDENT_5 << "" << std::endl; - + xmlWriter->writeStartElement(L"table:table-cell"); + xmlWriter->writeTextElement(L"text:p",{}, value); + xmlWriter->writeEndElement(); } void endOfPipe() { - if (valueCount) output << INDENT_4 << "" << std::endl; - if (relationCount) output << INDENT_3 << "" << std::endl; - output << INDENT_2 << "" << std::endl; - output << INDENT_1 << "" << std::endl; - output << "" << std::endl; + if (valueCount) xmlWriter->writeEndElement(); + if (relationCount) xmlWriter->writeEndElement(); + xmlWriter->writeEndElement(); + xmlWriter->writeEndElement(); + xmlWriter->writeEndElement(); } diff -r b99b1debb00c -r 0ba80e9b711f src/relpipe-out-ods.cpp --- a/src/relpipe-out-ods.cpp Thu Dec 20 00:26:00 2018 +0100 +++ b/src/relpipe-out-ods.cpp Sun Jan 06 22:15:38 2019 +0100 @@ -24,12 +24,14 @@ #include #include #include +#include #include "OdsHandler.h" using namespace relpipe::cli; using namespace relpipe::reader; using namespace relpipe::out::ods; +using namespace relpipe::xmlwriter; int main(int argc, char** argv) { setlocale(LC_ALL, ""); @@ -57,6 +59,9 @@ fwprintf(stderr, L"Caught Reader exception: %ls\n", e.getMessge().c_str()); fwprintf(stderr, L"Debug: Input stream: eof=%ls, lastRead=%d\n", (cin.eof() ? L"true" : L"false"), cin.gcount()); resultCode = CLI::EXIT_CODE_DATA_ERROR; + } catch (RelpipeXMLWriterException e) { + fwprintf(stderr, L"Error while writing XML: %ls\n", e.getMessge().c_str()); + resultCode = CLI::EXIT_CODE_UNEXPECTED_ERROR; } return resultCode;