--- a/src/XMLDocumentConstructor.h Tue Oct 27 00:59:54 2020 +0100
+++ b/src/XMLDocumentConstructor.h Tue Oct 27 22:39:50 2020 +0100
@@ -21,6 +21,7 @@
namespace xmltable {
#include <codecvt>
+#include <vector>
#include <libxml++-2.6/libxml++/libxml++.h>
#include <yaml.h>
@@ -31,13 +32,23 @@
xmlpp::DomParser* parser = nullptr;
yaml_parser_t yamlParser;
+ enum class Mode {
+ ROOT,
+ SEQUENCE,
+ MAPPING,
+ MAP_KEY
+ };
+
+ xmlpp::Element* current;
+ std::vector<Mode> mode;
+
static int readFromInput(void* instance, unsigned char* buffer, size_t size, size_t* length) {
std::istream* input = ((XMLDocumentConstructor*) instance)->input;
input->read((char*) buffer, size);
*length = input->gcount();
return (input->good() || input->eof()) ? 1 : 0;
}
-
+
/**
* Both YAML and XML strings are in UTF-8.
*/
@@ -45,6 +56,16 @@
return value ? (const char*) value : "";
}
+ const std::string y2xname(yaml_char_t* value) {
+ // FIXME: escaping, assure valid XML names
+ //return std::string("name_") + y2x(value);
+ return y2x(value);
+ }
+
+ xmlpp::Element* parentOrSelf(xmlpp::Element* current) {
+ return current->get_parent() == nullptr ? current : current->get_parent();
+ }
+
public:
XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) {
@@ -57,7 +78,8 @@
}
void process() {
- xmlpp::Element* root = parser->get_document()->create_root_node("yaml");
+ current = parser->get_document()->create_root_node("yaml");
+ mode.push_back(Mode::ROOT);
while (true) {
yaml_event_t event;
@@ -70,34 +92,66 @@
if (event.type == YAML_STREAM_END_EVENT) {
- xmlpp::Element* e = root->add_child("YAML_STREAM_END_EVENT");
+ std::cerr << "YAML_STREAM_END_EVENT" << std::endl;
yaml_event_delete(&event);
break;
} else if (event.type == YAML_STREAM_START_EVENT) {
- xmlpp::Element* e = root->add_child("YAML_STREAM_START_EVENT");
+ std::cerr << "YAML_STREAM_START_EVENT" << std::endl;
} else if (event.type == YAML_NO_EVENT) {
- xmlpp::Element* e = root->add_child("YAML_NO_EVENT");
+ std::cerr << "YAML_NO_EVENT" << std::endl;
+ current->add_child("null"); // TODO: null?
} else if (event.type == YAML_DOCUMENT_START_EVENT) {
- xmlpp::Element* e = root->add_child("YAML_DOCUMENT_START_EVENT");
+ std::cerr << "YAML_DOCUMENT_START_EVENT" << std::endl;
} else if (event.type == YAML_DOCUMENT_END_EVENT) {
- xmlpp::Element* e = root->add_child("YAML_DOCUMENT_END_EVENT");
+ std::cerr << "YAML_DOCUMENT_END_EVENT" << std::endl;
} else if (event.type == YAML_ALIAS_EVENT) {
- xmlpp::Element* e = root->add_child("YAML_ALIAS_EVENT");
+ std::cerr << "YAML_ALIAS_EVENT" << std::endl;
+ // TODO: alias?
} else if (event.type == YAML_SCALAR_EVENT) {
- xmlpp::Element* e = root->add_child("YAML_SCALAR_EVENT");
- e->set_attribute("value", y2x(event.data.scalar.value));
- e->set_attribute("anchor", y2x(event.data.scalar.anchor));
- e->set_attribute("tag", y2x(event.data.scalar.tag));
- e->set_attribute("style", std::to_string(event.data.scalar.style));
+ if (mode.back() == Mode::SEQUENCE) {
+ std::cerr << "YAML_SCALAR_EVENT: Mode::SEQUENCE: " << event.data.scalar.value << std::endl;
+ current->add_child("item")->add_child_text(y2x(event.data.scalar.value));
+ } else if (mode.back() == Mode::MAPPING) {
+ std::cerr << "YAML_SCALAR_EVENT: Mode::MAPPING: " << event.data.scalar.value << std::endl;
+ current = current->add_child(y2xname(event.data.scalar.value));
+ mode.push_back(Mode::MAP_KEY);
+ } else if (mode.back() == Mode::MAP_KEY) {
+ std::cerr << "YAML_SCALAR_EVENT: Mode::MAP_KEY: " << event.data.scalar.value << std::endl;
+ current->add_child_text(y2x(event.data.scalar.value));
+ current = parentOrSelf(current);
+ mode.pop_back();
+ } else {
+ std::cerr << "YAML_SCALAR_EVENT: ???" << std::endl;
+ }
+
} else if (event.type == YAML_SEQUENCE_START_EVENT) {
- xmlpp::Element* e = root->add_child("YAML_SEQUENCE_START_EVENT");
- e->set_attribute("style", std::to_string(event.data.sequence_start.style));
+ std::cerr << "YAML_SEQUENCE_START_EVENT" << std::endl;
+ if (mode.back() == Mode::MAP_KEY) mode.pop_back();
+ mode.push_back(Mode::SEQUENCE);
} else if (event.type == YAML_SEQUENCE_END_EVENT) {
- xmlpp::Element* e = root->add_child("YAML_SEQUENCE_END_EVENT");
+ std::cerr << "YAML_SEQUENCE_END_EVENT" << std::endl;
+ current = parentOrSelf(current);
+ mode.pop_back(); // TODO: assert sequence?
} else if (event.type == YAML_MAPPING_START_EVENT) {
- xmlpp::Element* e = root->add_child("YAML_MAPPING_START_EVENT");
+
+ if (mode.back() == Mode::SEQUENCE) {
+ std::cerr << "YAML_MAPPING_START_EVENT: Mode::SEQUENCE" << std::endl;
+ current = current->add_child("item");
+ } else if (mode.back() == Mode::MAP_KEY) {
+ std::cerr << "YAML_MAPPING_START_EVENT: Mode::MAP_KEY" << std::endl;
+ mode.pop_back();
+ } else {
+ std::cerr << "YAML_MAPPING_START_EVENT: Mode::?" << std::endl;
+ // TODO: map might be a key of another map → wrap/nest
+ }
+
+ mode.push_back(Mode::MAPPING);
} else if (event.type == YAML_MAPPING_END_EVENT) {
- xmlpp::Element* e = root->add_child("YAML_MAPPING_END_EVENT");
+ std::cerr << "YAML_MAPPING_END_EVENT" << std::endl;
+ current = parentOrSelf(current);
+ mode.pop_back(); // TODO: assert map?
+ } else {
+ std::cerr << "???" << std::endl;
}
yaml_event_delete(&event);
@@ -109,4 +163,4 @@
}
}
-}
\ No newline at end of file
+}