src/XMLTableCommand.h
branchv_0
changeset 8 8730e2d0db0e
parent 7 ff69af3c67a3
child 14 5be268bc4c69
equal deleted inserted replaced
7:ff69af3c67a3 8:8730e2d0db0e
    20 #include <iostream>
    20 #include <iostream>
    21 #include <string>
    21 #include <string>
    22 #include <sstream>
    22 #include <sstream>
    23 #include <vector>
    23 #include <vector>
    24 #include <algorithm>
    24 #include <algorithm>
       
    25 #include <exception>
       
    26 #include <regex>
    25 
    27 
    26 #include <libxml++-2.6/libxml++/libxml++.h>
    28 #include <libxml++-2.6/libxml++/libxml++.h>
    27 
    29 
    28 #include <relpipe/writer/typedefs.h>
    30 #include <relpipe/writer/typedefs.h>
    29 
    31 
    36 using namespace relpipe::writer;
    38 using namespace relpipe::writer;
    37 
    39 
    38 class XMLCommand {
    40 class XMLCommand {
    39 private:
    41 private:
    40 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
    42 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
       
    43 
       
    44 	string_t formatRawXML(string_t rawXML) {
       
    45 		std::wregex pattern(L"^<\\?xml version=\"1.0\" encoding=\"UTF-8\"\\?>\n|\n$");
       
    46 		return std::regex_replace(rawXML, pattern, L"");
       
    47 	}
       
    48 
       
    49 	void importNode(xmlpp::Node* parent, xmlpp::Node* child, AttributeRecipe attributeRecipe) {
       
    50 		if (dynamic_cast<xmlpp::AttributeNode*> (child)) parent->add_child_with_new_ns(
       
    51 				convertor.to_bytes(attributeRecipe.rawXmlAttributeWrapper.name),
       
    52 				convertor.to_bytes(attributeRecipe.rawXmlAttributeWrapper.uri),
       
    53 				convertor.to_bytes(attributeRecipe.rawXmlAttributeWrapper.prefix))->import_node(child);
       
    54 		else parent->import_node(child, true);
       
    55 	}
       
    56 
       
    57 	void importNode(xmlpp::Document* document, xmlpp::Node* child, AttributeRecipe attributeRecipe) {
       
    58 		if (dynamic_cast<xmlpp::AttributeNode*> (child)) document->create_root_node(
       
    59 				convertor.to_bytes(attributeRecipe.rawXmlAttributeWrapper.name),
       
    60 				convertor.to_bytes(attributeRecipe.rawXmlAttributeWrapper.uri),
       
    61 				convertor.to_bytes(attributeRecipe.rawXmlAttributeWrapper.prefix))->import_node(child);
       
    62 		else document->create_root_node_by_import(child, true);
       
    63 	}
       
    64 
       
    65 	string_t toRawXML(xmlpp::Node* parent, AttributeRecipe attributeRecipe, xmlpp::Node::PrefixNsMap ns) {
       
    66 		xmlpp::Document d;
       
    67 		xmlpp::NodeSet nodes = parent->find(convertor.to_bytes(attributeRecipe.xpath), ns);
       
    68 
       
    69 		if (attributeRecipe.rawXmlNodeListWrapper.name.size()) {
       
    70 			d.create_root_node(
       
    71 					convertor.to_bytes(attributeRecipe.rawXmlNodeListWrapper.name),
       
    72 					convertor.to_bytes(attributeRecipe.rawXmlNodeListWrapper.uri),
       
    73 					convertor.to_bytes(attributeRecipe.rawXmlNodeListWrapper.prefix));
       
    74 			for (xmlpp::Node* node : nodes) importNode(d.get_root_node(), node, attributeRecipe);
       
    75 		} else {
       
    76 			if (nodes.size() == 1) importNode(&d, nodes[0], attributeRecipe);
       
    77 			else if (nodes.size() > 1) throw std::invalid_argument("Multiple nodes found where only one was expected. Use nodelist wrapper."); // TODO: better relpipe exception
       
    78 			else return L""; // TODO: null
       
    79 		}
       
    80 		return formatRawXML(convertor.from_bytes(d.write_to_string()));
       
    81 	}
    41 
    82 
    42 public:
    83 public:
    43 
    84 
    44 	void process(std::istream& input, std::ostream& output, Configuration& configuration) {
    85 	void process(std::istream& input, std::ostream& output, Configuration& configuration) {
    45 		std::shared_ptr<RelationalWriter> writer(Factory::create(output));
    86 		std::shared_ptr<RelationalWriter> writer(Factory::create(output));
    62 			relpipe::writer::string_t name = r.nameIsXPath ? convertor.from_bytes(root->eval_to_string(convertor.to_bytes(r.relation), ns)) : r.relation;
   103 			relpipe::writer::string_t name = r.nameIsXPath ? convertor.from_bytes(root->eval_to_string(convertor.to_bytes(r.relation), ns)) : r.relation;
    63 			writer->startRelation(name, attributesMetadata, true);
   104 			writer->startRelation(name, attributesMetadata, true);
    64 			for (xmlpp::Node* n : root->find(convertor.to_bytes(r.xpath), ns)) {
   105 			for (xmlpp::Node* n : root->find(convertor.to_bytes(r.xpath), ns)) {
    65 				for (AttributeRecipe a : r.attributes) {
   106 				for (AttributeRecipe a : r.attributes) {
    66 					// TODO: convert to bytes only once
   107 					// TODO: convert to bytes only once
    67 					writer->writeAttribute(convertor.from_bytes(n->eval_to_string(convertor.to_bytes(a.xpath), ns)));
   108 					std::string attributeXpath = convertor.to_bytes(a.xpath);
       
   109 					if (a.mode == Mode::STRING) {
       
   110 						writer->writeAttribute(convertor.from_bytes(n->eval_to_string(attributeXpath, ns)));
       
   111 					} else if (a.mode == Mode::BOOLEAN) {
       
   112 						writer->writeAttribute(n->eval_to_boolean(attributeXpath, ns) ? L"true" : L"false");
       
   113 					} else if (a.mode == Mode::LINE_NUMBER) {
       
   114 						xmlpp::NodeSet attributeNodes = n->find(attributeXpath, ns);
       
   115 						string_t line = attributeNodes.size() ? std::to_wstring(attributeNodes[0]->get_line()) : L""; // TODO: null
       
   116 						writer->writeAttribute(line);
       
   117 					} else if (a.mode == Mode::XPATH) {
       
   118 						xmlpp::NodeSet attributeNodes = n->find(attributeXpath, ns);
       
   119 						string_t line = attributeNodes.size() ? convertor.from_bytes(attributeNodes[0]->get_path()) : L""; // TODO: null
       
   120 						writer->writeAttribute(line);
       
   121 					} else if (a.mode == Mode::RAW_XML) {
       
   122 						writer->writeAttribute(toRawXML(n, a, ns));
       
   123 					} else {
       
   124 						throw logic_error("Unsupported mode."); // should never happer, TODO: better relpipe exception
       
   125 					}
    68 				}
   126 				}
    69 			}
   127 			}
    70 		}
   128 		}
    71 	}
   129 	}
    72 };
   130 };