src/XMLDocumentConstructor.h
branchv_0
changeset 17 75c6685cceb9
parent 16 3b197bf7a231
child 18 737c507a3e32
equal deleted inserted replaced
16:3b197bf7a231 17:75c6685cceb9
    19 namespace relpipe {
    19 namespace relpipe {
    20 namespace in {
    20 namespace in {
    21 namespace xmltable {
    21 namespace xmltable {
    22 
    22 
    23 #include <codecvt>
    23 #include <codecvt>
       
    24 #include <vector>
    24 
    25 
    25 #include <libxml++-2.6/libxml++/libxml++.h>
    26 #include <libxml++-2.6/libxml++/libxml++.h>
    26 #include <yaml.h>
    27 #include <yaml.h>
    27 
    28 
    28 class XMLDocumentConstructor {
    29 class XMLDocumentConstructor {
    29 private:
    30 private:
    30 	std::istream* input = nullptr;
    31 	std::istream* input = nullptr;
    31 	xmlpp::DomParser* parser = nullptr;
    32 	xmlpp::DomParser* parser = nullptr;
    32 	yaml_parser_t yamlParser;
    33 	yaml_parser_t yamlParser;
    33 
    34 
       
    35 	enum class Mode {
       
    36 		ROOT,
       
    37 		SEQUENCE,
       
    38 		MAPPING,
       
    39 		MAP_KEY
       
    40 	};
       
    41 
       
    42 	xmlpp::Element* current;
       
    43 	std::vector<Mode> mode;
       
    44 
    34 	static int readFromInput(void* instance, unsigned char* buffer, size_t size, size_t* length) {
    45 	static int readFromInput(void* instance, unsigned char* buffer, size_t size, size_t* length) {
    35 		std::istream* input = ((XMLDocumentConstructor*) instance)->input;
    46 		std::istream* input = ((XMLDocumentConstructor*) instance)->input;
    36 		input->read((char*) buffer, size);
    47 		input->read((char*) buffer, size);
    37 		*length = input->gcount();
    48 		*length = input->gcount();
    38 		return (input->good() || input->eof()) ? 1 : 0;
    49 		return (input->good() || input->eof()) ? 1 : 0;
    39 	}
    50 	}
    40 	
    51 
    41 	/**
    52 	/**
    42 	 * Both YAML and XML strings are in UTF-8.
    53 	 * Both YAML and XML strings are in UTF-8.
    43 	 */
    54 	 */
    44 	const char* y2x(yaml_char_t* value) {
    55 	const char* y2x(yaml_char_t* value) {
    45 		return value ? (const char*) value : "";
    56 		return value ? (const char*) value : "";
       
    57 	}
       
    58 
       
    59 	const std::string y2xname(yaml_char_t* value) {
       
    60 		// FIXME: escaping, assure valid XML names
       
    61 		//return std::string("name_") + y2x(value);
       
    62 		return y2x(value);
       
    63 	}
       
    64 
       
    65 	xmlpp::Element* parentOrSelf(xmlpp::Element* current) {
       
    66 		return current->get_parent() == nullptr ? current : current->get_parent();
    46 	}
    67 	}
    47 
    68 
    48 public:
    69 public:
    49 
    70 
    50 	XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) {
    71 	XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) {
    55 	virtual ~XMLDocumentConstructor() {
    76 	virtual ~XMLDocumentConstructor() {
    56 		yaml_parser_delete(&yamlParser);
    77 		yaml_parser_delete(&yamlParser);
    57 	}
    78 	}
    58 
    79 
    59 	void process() {
    80 	void process() {
    60 		xmlpp::Element* root = parser->get_document()->create_root_node("yaml");
    81 		current = parser->get_document()->create_root_node("yaml");
       
    82 		mode.push_back(Mode::ROOT);
    61 
    83 
    62 		while (true) {
    84 		while (true) {
    63 			yaml_event_t event;
    85 			yaml_event_t event;
    64 
    86 
    65 			if (!yaml_parser_parse(&yamlParser, &event)) {
    87 			if (!yaml_parser_parse(&yamlParser, &event)) {
    68 				return;
    90 				return;
    69 			}
    91 			}
    70 
    92 
    71 
    93 
    72 			if (event.type == YAML_STREAM_END_EVENT) {
    94 			if (event.type == YAML_STREAM_END_EVENT) {
    73 				xmlpp::Element* e = root->add_child("YAML_STREAM_END_EVENT");
    95 				std::cerr << "YAML_STREAM_END_EVENT" << std::endl;
    74 				yaml_event_delete(&event);
    96 				yaml_event_delete(&event);
    75 				break;
    97 				break;
    76 			} else if (event.type == YAML_STREAM_START_EVENT) {
    98 			} else if (event.type == YAML_STREAM_START_EVENT) {
    77 				xmlpp::Element* e = root->add_child("YAML_STREAM_START_EVENT");
    99 				std::cerr << "YAML_STREAM_START_EVENT" << std::endl;
    78 			} else if (event.type == YAML_NO_EVENT) {
   100 			} else if (event.type == YAML_NO_EVENT) {
    79 				xmlpp::Element* e = root->add_child("YAML_NO_EVENT");
   101 				std::cerr << "YAML_NO_EVENT" << std::endl;
       
   102 				current->add_child("null"); // TODO: null?
    80 			} else if (event.type == YAML_DOCUMENT_START_EVENT) {
   103 			} else if (event.type == YAML_DOCUMENT_START_EVENT) {
    81 				xmlpp::Element* e = root->add_child("YAML_DOCUMENT_START_EVENT");
   104 				std::cerr << "YAML_DOCUMENT_START_EVENT" << std::endl;
    82 			} else if (event.type == YAML_DOCUMENT_END_EVENT) {
   105 			} else if (event.type == YAML_DOCUMENT_END_EVENT) {
    83 				xmlpp::Element* e = root->add_child("YAML_DOCUMENT_END_EVENT");
   106 				std::cerr << "YAML_DOCUMENT_END_EVENT" << std::endl;
    84 			} else if (event.type == YAML_ALIAS_EVENT) {
   107 			} else if (event.type == YAML_ALIAS_EVENT) {
    85 				xmlpp::Element* e = root->add_child("YAML_ALIAS_EVENT");
   108 				std::cerr << "YAML_ALIAS_EVENT" << std::endl;
       
   109 				// TODO: alias?
    86 			} else if (event.type == YAML_SCALAR_EVENT) {
   110 			} else if (event.type == YAML_SCALAR_EVENT) {
    87 				xmlpp::Element* e = root->add_child("YAML_SCALAR_EVENT");
   111 				if (mode.back() == Mode::SEQUENCE) {
    88 				e->set_attribute("value", y2x(event.data.scalar.value));
   112 					std::cerr << "YAML_SCALAR_EVENT: Mode::SEQUENCE: " << event.data.scalar.value << std::endl;
    89 				e->set_attribute("anchor", y2x(event.data.scalar.anchor));
   113 					current->add_child("item")->add_child_text(y2x(event.data.scalar.value));
    90 				e->set_attribute("tag", y2x(event.data.scalar.tag));
   114 				} else if (mode.back() == Mode::MAPPING) {
    91 				e->set_attribute("style", std::to_string(event.data.scalar.style));
   115 					std::cerr << "YAML_SCALAR_EVENT: Mode::MAPPING: " << event.data.scalar.value << std::endl;
       
   116 					current = current->add_child(y2xname(event.data.scalar.value));
       
   117 					mode.push_back(Mode::MAP_KEY);
       
   118 				} else if (mode.back() == Mode::MAP_KEY) {
       
   119 					std::cerr << "YAML_SCALAR_EVENT: Mode::MAP_KEY: " << event.data.scalar.value << std::endl;
       
   120 					current->add_child_text(y2x(event.data.scalar.value));
       
   121 					current = parentOrSelf(current);
       
   122 					mode.pop_back();
       
   123 				} else {
       
   124 					std::cerr << "YAML_SCALAR_EVENT: ???" << std::endl;
       
   125 				}
       
   126 
    92 			} else if (event.type == YAML_SEQUENCE_START_EVENT) {
   127 			} else if (event.type == YAML_SEQUENCE_START_EVENT) {
    93 				xmlpp::Element* e = root->add_child("YAML_SEQUENCE_START_EVENT");
   128 				std::cerr << "YAML_SEQUENCE_START_EVENT" << std::endl;
    94 				e->set_attribute("style", std::to_string(event.data.sequence_start.style));
   129 				if (mode.back() == Mode::MAP_KEY) mode.pop_back();
       
   130 				mode.push_back(Mode::SEQUENCE);
    95 			} else if (event.type == YAML_SEQUENCE_END_EVENT) {
   131 			} else if (event.type == YAML_SEQUENCE_END_EVENT) {
    96 				xmlpp::Element* e = root->add_child("YAML_SEQUENCE_END_EVENT");
   132 				std::cerr << "YAML_SEQUENCE_END_EVENT" << std::endl;
       
   133 				current = parentOrSelf(current);
       
   134 				mode.pop_back(); // TODO: assert sequence?
    97 			} else if (event.type == YAML_MAPPING_START_EVENT) {
   135 			} else if (event.type == YAML_MAPPING_START_EVENT) {
    98 				xmlpp::Element* e = root->add_child("YAML_MAPPING_START_EVENT");
   136 
       
   137 				if (mode.back() == Mode::SEQUENCE) {
       
   138 					std::cerr << "YAML_MAPPING_START_EVENT: Mode::SEQUENCE" << std::endl;
       
   139 					current = current->add_child("item");
       
   140 				} else if (mode.back() == Mode::MAP_KEY) {
       
   141 					std::cerr << "YAML_MAPPING_START_EVENT: Mode::MAP_KEY" << std::endl;
       
   142 					mode.pop_back();
       
   143 				} else {
       
   144 					std::cerr << "YAML_MAPPING_START_EVENT: Mode::?" << std::endl;
       
   145 					// TODO: map might be a key of another map → wrap/nest
       
   146 				}
       
   147 
       
   148 				mode.push_back(Mode::MAPPING);
    99 			} else if (event.type == YAML_MAPPING_END_EVENT) {
   149 			} else if (event.type == YAML_MAPPING_END_EVENT) {
   100 				xmlpp::Element* e = root->add_child("YAML_MAPPING_END_EVENT");
   150 				std::cerr << "YAML_MAPPING_END_EVENT" << std::endl;
       
   151 				current = parentOrSelf(current);
       
   152 				mode.pop_back(); // TODO: assert map?
       
   153 			} else {
       
   154 				std::cerr << "???" << std::endl;
   101 			}
   155 			}
   102 
   156 
   103 			yaml_event_delete(&event);
   157 			yaml_event_delete(&event);
   104 		}
   158 		}
   105 
   159