# HG changeset patch # User František Kučera # Date 1537114351 -7200 # Node ID 13a41e435ea01c0914b350b8e5c77dda23c8dcee # Parent 82ba555a97d107ad071dc4fb168a445cb030ed8f quick and dirty XML output diff -r 82ba555a97d1 -r 13a41e435ea0 src/XmlHandler.h --- a/src/XmlHandler.h Sun Sep 16 14:39:10 2018 +0200 +++ b/src/XmlHandler.h Sun Sep 16 18:12:31 2018 +0200 @@ -29,25 +29,30 @@ std::vector columnTypes; std::vector columnTypeCodes; std::vector columnNames; - std::vector columnWidths; - std::vector values; // all values are saved here and processed at the end of the relation + integer_t valueCount = 0; integer_t columnCount = 0; + integer_t relationCount = 0; - - - const string_t escapeXmlText(const string_t &value, const char* color) { + const std::string escapeXmlText(const string_t &value) { std::wstringstream result; for (auto & ch : value) { switch (ch) { - // FIXME: xml escaping 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 result.str(); + return convertor.to_bytes(result.str()); } public: @@ -56,27 +61,58 @@ } void startRelation(string_t name, std::vector attributes) override { - output << convertor.to_bytes(name) << ": (XML)" << endl; + // 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 + } else { + output << INDENT << INDENT << "" << std::endl; + output << INDENT << "" << std::endl; + } + relationCount++; + output << INDENT << "" << std::endl; + + output << INDENT << INDENT << "" << escapeXmlText(name) << "" << std::endl; + + columnCount = attributes.size(); columnTypes.resize(columnCount); columnTypeCodes.resize(columnCount); columnNames.resize(columnCount); - columnWidths.resize(columnCount, 0); for (int i = 0; i < attributes.size(); i++) { columnNames[i] = attributes[i].getAttributeName(); columnTypes[i] = attributes[i].getTypeId(); columnTypeCodes[i] = attributes[i].getTypeName(); } + + // TODO: print attribute metadata } void attribute(const string_t& value) override { - integer_t i = values.size() % columnCount; - values.push_back(value); - columnWidths[i] = max(columnWidths[i], value.length()); + integer_t i = valueCount % columnCount; + + if (i == 0 && valueCount) output << INDENT << INDENT << "" << std::endl; + if (i == 0) output << INDENT << INDENT << "" << std::endl; + + valueCount++; + + // TODO: print attribute metadata (optional) + output << INDENT << INDENT << INDENT << ""; + output << escapeXmlText(value); + output << "" << std::endl; + } void endOfPipe() { - + if (valueCount) output << INDENT << INDENT << "" << std::endl; + if (relationCount) output << INDENT << "" << std::endl; + output << "" << std::endl; + } }; diff -r 82ba555a97d1 -r 13a41e435ea0 src/relpipe-out-xml.cpp --- a/src/relpipe-out-xml.cpp Sun Sep 16 14:39:10 2018 +0200 +++ b/src/relpipe-out-xml.cpp Sun Sep 16 18:12:31 2018 +0200 @@ -1,4 +1,5 @@ #include +#include #include #include @@ -19,6 +20,11 @@ int resultCode = CLI::EXIT_CODE_UNEXPECTED_ERROR; try { + + // TODO: color syntax highlighting if stdout is TTY: + // if (isatty(fileno(stdout))) std::cout << "color" << std::endl; + // else std::cout << "no-color" << std::endl; + std::shared_ptr reader(Factory::create(std::cin)); XmlHandler handler(std::cout); reader->addHandler(&handler);