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(); } };