# HG changeset patch # User František Kučera # Date 1546809338 -3600 # Node ID 816094aa1fff3aeca04335130e9c31a88b46cf10 # Parent b8274181b061601bd45a03b20dccf597d1445839 move common XML code to relpipe-lib-xmlwriter (a header-only library) diff -r b8274181b061 -r 816094aa1fff nbproject/configurations.xml --- a/nbproject/configurations.xml Sat Jan 05 18:38:14 2019 +0100 +++ b/nbproject/configurations.xml Sun Jan 06 22:15:38 2019 +0100 @@ -76,6 +76,14 @@ ${MAKE} -f Makefile ${MAKE} -f Makefile clean build/Debug/src/relpipe-out-xml + + + ../relpipe-lib-reader.cpp/include + ../relpipe-lib-cli.cpp/include + ../relpipe-lib-xmlwriter.cpp/include + build/Debug/src + + build/Debug @@ -85,11 +93,6 @@ - - ../relpipe-lib-reader.cpp/include - ../relpipe-lib-cli.cpp/include - build/Debug/src - diff -r b8274181b061 -r 816094aa1fff src/CMakeLists.txt --- a/src/CMakeLists.txt Sat Jan 05 18:38:14 2019 +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 b8274181b061 -r 816094aa1fff src/XmlHandler.h --- a/src/XmlHandler.h Sat Jan 05 18:38:14 2019 +0100 +++ b/src/XmlHandler.h Sun Jan 06 22:15:38 2019 +0100 @@ -29,20 +29,18 @@ #include #include #include +#include namespace relpipe { namespace out { namespace xml { using namespace relpipe::reader; +using namespace relpipe::xmlwriter; class XmlHandler : public handlers::RelationalReaderStringHadler { private: - std::wstring_convert> convertor; // XML output will be always in UTF-8 - const char* INDENT = "\t"; - - std::ostream &output; - + shared_ptr xmlWriter; std::vector columnTypes; std::vector columnTypeCodes; std::vector columnNames; @@ -50,53 +48,25 @@ integer_t columnCount = 0; integer_t relationCount = 0; - const std::string escapeXmlText(const string_t &value) { - // TODO: really bad performance → rewrite - // 72 % of whole relpipe-out-xml according to valgrind/callgrind - 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: - XmlHandler(std::ostream& output) : output(output) { + XmlHandler(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; - // TODO: xmlns + xmlWriter->writeStartElement(L"pipe",{L"xmlns", L"tag:globalcode.info,2018:relpipe"}); } else { - output << INDENT << INDENT << "" << std::endl; - output << INDENT << "" << std::endl; + xmlWriter->writeEndElement(); + xmlWriter->writeEndElement(); } relationCount++; - output << INDENT << "" << std::endl; + xmlWriter->writeStartElement(L"relation"); - output << INDENT << INDENT << "" << escapeXmlText(name) << "" << std::endl; + xmlWriter->writeTextElement(L"name",{}, name); columnCount = attributes.size(); @@ -108,30 +78,27 @@ columnTypes[i] = attributes[i].getTypeId(); columnTypeCodes[i] = attributes[i].getTypeName(); } - + // TODO: print attribute metadata } void attribute(const string_t& value) override { integer_t i = valueCount % columnCount; - if (i == 0 && valueCount) output << INDENT << INDENT << "" << std::endl; - if (i == 0) output << INDENT << INDENT << "" << std::endl; + if (i == 0 && valueCount) xmlWriter->writeEndElement(); + if (i == 0) xmlWriter->writeStartElement(L"record"); valueCount++; // TODO: print attribute metadata (optional) - output << INDENT << INDENT << INDENT << ""; - output << escapeXmlText(value); - output << "" << std::endl; + xmlWriter->writeTextElement(L"attribute",{}, value); } void endOfPipe() { - if (valueCount) output << INDENT << INDENT << "" << std::endl; - if (relationCount) output << INDENT << "" << std::endl; - output << "" << std::endl; - + if (valueCount) xmlWriter->writeEndElement(); + if (relationCount) xmlWriter->writeEndElement(); + xmlWriter->writeEndElement(); } }; diff -r b8274181b061 -r 816094aa1fff src/relpipe-out-xml.cpp --- a/src/relpipe-out-xml.cpp Sat Jan 05 18:38:14 2019 +0100 +++ b/src/relpipe-out-xml.cpp Sun Jan 06 22:15:38 2019 +0100 @@ -24,12 +24,14 @@ #include #include #include +#include #include "XmlHandler.h" using namespace relpipe::cli; using namespace relpipe::reader; using namespace relpipe::out::xml; +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;