diff -r ff69af3c67a3 -r 8730e2d0db0e src/XMLTableCommand.h --- a/src/XMLTableCommand.h Thu Jan 02 23:31:44 2020 +0100 +++ b/src/XMLTableCommand.h Sun Jan 05 01:01:12 2020 +0100 @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include @@ -39,6 +41,45 @@ private: std::wstring_convert> convertor; // TODO: support also other encodings. + string_t formatRawXML(string_t rawXML) { + std::wregex pattern(L"^<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>\n|\n$"); + return std::regex_replace(rawXML, pattern, L""); + } + + void importNode(xmlpp::Node* parent, xmlpp::Node* child, AttributeRecipe attributeRecipe) { + if (dynamic_cast (child)) parent->add_child_with_new_ns( + convertor.to_bytes(attributeRecipe.rawXmlAttributeWrapper.name), + convertor.to_bytes(attributeRecipe.rawXmlAttributeWrapper.uri), + convertor.to_bytes(attributeRecipe.rawXmlAttributeWrapper.prefix))->import_node(child); + else parent->import_node(child, true); + } + + void importNode(xmlpp::Document* document, xmlpp::Node* child, AttributeRecipe attributeRecipe) { + if (dynamic_cast (child)) document->create_root_node( + convertor.to_bytes(attributeRecipe.rawXmlAttributeWrapper.name), + convertor.to_bytes(attributeRecipe.rawXmlAttributeWrapper.uri), + convertor.to_bytes(attributeRecipe.rawXmlAttributeWrapper.prefix))->import_node(child); + else document->create_root_node_by_import(child, true); + } + + string_t toRawXML(xmlpp::Node* parent, AttributeRecipe attributeRecipe, xmlpp::Node::PrefixNsMap ns) { + xmlpp::Document d; + xmlpp::NodeSet nodes = parent->find(convertor.to_bytes(attributeRecipe.xpath), ns); + + if (attributeRecipe.rawXmlNodeListWrapper.name.size()) { + d.create_root_node( + convertor.to_bytes(attributeRecipe.rawXmlNodeListWrapper.name), + convertor.to_bytes(attributeRecipe.rawXmlNodeListWrapper.uri), + convertor.to_bytes(attributeRecipe.rawXmlNodeListWrapper.prefix)); + for (xmlpp::Node* node : nodes) importNode(d.get_root_node(), node, attributeRecipe); + } else { + if (nodes.size() == 1) importNode(&d, nodes[0], attributeRecipe); + else if (nodes.size() > 1) throw std::invalid_argument("Multiple nodes found where only one was expected. Use nodelist wrapper."); // TODO: better relpipe exception + else return L""; // TODO: null + } + return formatRawXML(convertor.from_bytes(d.write_to_string())); + } + public: void process(std::istream& input, std::ostream& output, Configuration& configuration) { @@ -64,7 +105,24 @@ for (xmlpp::Node* n : root->find(convertor.to_bytes(r.xpath), ns)) { for (AttributeRecipe a : r.attributes) { // TODO: convert to bytes only once - writer->writeAttribute(convertor.from_bytes(n->eval_to_string(convertor.to_bytes(a.xpath), ns))); + std::string attributeXpath = convertor.to_bytes(a.xpath); + if (a.mode == Mode::STRING) { + writer->writeAttribute(convertor.from_bytes(n->eval_to_string(attributeXpath, ns))); + } else if (a.mode == Mode::BOOLEAN) { + writer->writeAttribute(n->eval_to_boolean(attributeXpath, ns) ? L"true" : L"false"); + } else if (a.mode == Mode::LINE_NUMBER) { + xmlpp::NodeSet attributeNodes = n->find(attributeXpath, ns); + string_t line = attributeNodes.size() ? std::to_wstring(attributeNodes[0]->get_line()) : L""; // TODO: null + writer->writeAttribute(line); + } else if (a.mode == Mode::XPATH) { + xmlpp::NodeSet attributeNodes = n->find(attributeXpath, ns); + string_t line = attributeNodes.size() ? convertor.from_bytes(attributeNodes[0]->get_path()) : L""; // TODO: null + writer->writeAttribute(line); + } else if (a.mode == Mode::RAW_XML) { + writer->writeAttribute(toRawXML(n, a, ns)); + } else { + throw logic_error("Unsupported mode."); // should never happer, TODO: better relpipe exception + } } } }