src/XMLDocumentConstructor.h
branchv_0
changeset 31 c6527b45fbc2
parent 30 f686bdaeb9e0
child 32 e72546725c77
--- a/src/XMLDocumentConstructor.h	Sun Nov 29 00:30:36 2020 +0100
+++ b/src/XMLDocumentConstructor.h	Sun Nov 29 10:49:33 2020 +0100
@@ -38,6 +38,31 @@
 	xmlpp::DomParser* domParser;
 	XMLNameCodec nameCodec;
 	xmlpp::Element* currentSection = nullptr;
+
+	enum class TreeStyle {
+		Standard,
+		Literal,
+	};
+
+	TreeStyle parseTreeStyle(const std::string& name) {
+		if (name == "standard") return TreeStyle::Standard;
+		else if (name == "literal") return TreeStyle::Literal;
+		else throw std::invalid_argument(std::string("Unknown tree style: ") + name);
+	}
+
+	TreeStyle treeStyle = TreeStyle::Literal;
+
+	/**
+	 * TODO: use a common method
+	 */
+	bool parseBoolean(const std::string& value) {
+		if (value == "true") return true;
+		else if (value == "false") return false;
+		else throw std::invalid_argument(std::string("Unable to parse boolean value: ") + value + " (expecting true or false)");
+	}
+
+	bool treeWithNamespaces = false;
+
 public:
 
 	HierarchicalINIContentHandler(xmlpp::DomParser* domParser) : domParser(domParser) {
@@ -48,15 +73,15 @@
 
 	void startDocument() override {
 		if (currentSection) throw std::out_of_range("Lunatic INI parser send us multiple documents.");
-		currentSection = domParser->get_document()->create_root_node("ini");
+		currentSection = domParser->get_document()->create_root_node("ini", treeWithNamespaces ? xml::XMLNS : "");
 	};
 
 	void endDocument() override {
 	};
 
 	void startSection(const SectionStartEvent& event) override {
-		currentSection = currentSection->add_child(nameCodec.encode(event.name));
-		currentSection->set_attribute("type", "section");
+		currentSection = currentSection->add_child(treeStyle == TreeStyle::Literal ? nameCodec.encode(event.name) : "section");
+		if (treeStyle == TreeStyle::Literal) currentSection->set_attribute("type", "section");
 		currentSection->set_attribute("name", event.name);
 		if (event.comment.size()) currentSection->set_attribute("comment", event.comment);
 		if (event.lineNumber >= 0) currentSection->set_attribute("line-number", std::to_string(event.lineNumber));
@@ -69,8 +94,8 @@
 	};
 
 	void entry(const EntryEvent& event) override {
-		xmlpp::Element* entry = currentSection->add_child(nameCodec.encode(event.fullKey));
-		entry->set_attribute("type", "entry");
+		xmlpp::Element* entry = currentSection->add_child(treeStyle == TreeStyle::Literal ? nameCodec.encode(event.fullKey) : "entry");
+		if (treeStyle == TreeStyle::Literal) entry->set_attribute("type", "entry");
 		entry->set_attribute("key", event.key);
 		entry->set_attribute("full-key", event.fullKey);
 		if (event.subKey.size()) entry->set_attribute("sub-key", event.subKey);
@@ -82,18 +107,25 @@
 
 	void comment(const CommentEvent& event) override {
 		xmlpp::Element* comment = currentSection->add_child("comment");
-		comment->set_attribute("type", "comment");
+		if (treeStyle == TreeStyle::Literal) comment->set_attribute("type", "comment");
 		if (event.lineNumber >= 0) comment->set_attribute("line-number", std::to_string(event.lineNumber));
 		if (event.eventNumber >= 0) comment->set_attribute("event-number", std::to_string(event.eventNumber));
 		comment->add_child_text(event.comment);
 	}
 
 	void whitespace(const WhitespaceEvent& event) override {
-		xmlpp::Element* comment = currentSection->add_child("whitespace");
-		comment->set_attribute("type", "whitespace");
-		if (event.lineNumber >= 0) comment->set_attribute("line-number", std::to_string(event.lineNumber));
-		if (event.eventNumber >= 0) comment->set_attribute("event-number", std::to_string(event.eventNumber));
-		comment->add_child_text(event.whitespace);
+		xmlpp::Element* whitespace = currentSection->add_child("whitespace");
+		if (treeStyle == TreeStyle::Literal) whitespace->set_attribute("type", "whitespace");
+		if (event.lineNumber >= 0) whitespace->set_attribute("line-number", std::to_string(event.lineNumber));
+		if (event.eventNumber >= 0) whitespace->set_attribute("event-number", std::to_string(event.eventNumber));
+		whitespace->add_child_text(event.whitespace);
+	}
+
+	bool setOption(const std::string& uri, const std::string& value) {
+		if (uri == xml::TreeWithNamespaces) treeWithNamespaces = parseBoolean(value);
+		else if (uri == xml::TreeStyle) treeStyle = parseTreeStyle(value);
+		else return false;
+		return true;
 	}
 
 };
@@ -107,6 +139,7 @@
 	std::istream* input = nullptr;
 	xmlpp::DomParser* parser = nullptr;
 	std::shared_ptr<INIReader> reader;
+	std::shared_ptr<HierarchicalINIContentHandler> handler;
 public:
 
 	XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) {
@@ -115,15 +148,16 @@
 		reader->addUnescapingProcessor(std::make_shared<JavaPropertiesUnescapingProcessor>(), unescaping::JavaProperties, false);
 		reader->addUnescapingProcessor(std::make_shared<BackspaceUnescapingProcessor>(), unescaping::Backspace, true);
 		reader->addDialect(std::make_shared<JavaPropertiesDialect>(), dialect::JavaProperties, false);
+		handler = std::make_shared<HierarchicalINIContentHandler>(parser);
 	}
 
 	void setOption(const std::string& uri, const std::string& value) {
+		if (handler->setOption(uri, value)) return;
 		reader->setOption(uri, value);
 	}
 
 	void process() {
-		HierarchicalINIContentHandler handler(parser);
-		reader->addHandler(&handler);
+		reader->addHandler(handler.get());
 		reader->process();
 	}
 };