src/XMLDocumentConstructor.h
branchv_0
changeset 18 45c06bdf9045
parent 17 786977554fc3
child 19 90f2b8ca32bf
equal deleted inserted replaced
17:786977554fc3 18:45c06bdf9045
    14  * You should have received a copy of the GNU General Public License
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
    16  */
    16  */
    17 #pragma once
    17 #pragma once
    18 
    18 
       
    19 #include <stdexcept>
    19 #include <libxml++-2.6/libxml++/libxml++.h>
    20 #include <libxml++-2.6/libxml++/libxml++.h>
    20 
    21 
    21 #include "lib/INIReader.h"
    22 #include "lib/INIReader.h"
    22 #include "lib/XMLNameCodec.h"
    23 #include "lib/XMLNameCodec.h"
    23 
    24 
    26 namespace xmltable {
    27 namespace xmltable {
    27 
    28 
    28 class HierarchicalINIContentHandler : public INIContentHandler {
    29 class HierarchicalINIContentHandler : public INIContentHandler {
    29 private:
    30 private:
    30 	xmlpp::DomParser* domParser;
    31 	xmlpp::DomParser* domParser;
    31 	wstring_convert < codecvt_utf8<wchar_t>> convertor; // INI parser works with UTF-8
    32 	XMLNameCodec nameCodec;
       
    33 	xmlpp::Element* currentSection = nullptr;
    32 public:
    34 public:
    33 
    35 
    34 	HierarchicalINIContentHandler(xmlpp::DomParser* domParser) : domParser(domParser) {
    36 	HierarchicalINIContentHandler(xmlpp::DomParser* domParser) : domParser(domParser) {
    35 	}
    37 	}
    36 
    38 
    37 	virtual ~HierarchicalINIContentHandler() {
    39 	virtual ~HierarchicalINIContentHandler() {
    38 	}
    40 	}
    39 
    41 
    40 	void startDocument() override {
    42 	void startDocument() override {
    41 		domParser->get_document()->create_root_node("ini");
    43 		if (currentSection) throw std::out_of_range("Lunatic INI parser send us multiple documents.");
    42 		domParser->get_document()->get_root_node()->add_child("startDocument");
    44 		currentSection = domParser->get_document()->create_root_node("ini");
    43 		// there should be only one document
       
    44 	};
    45 	};
    45 
    46 
    46 	void endDocument() override {
    47 	void endDocument() override {
    47 		domParser->get_document()->get_root_node()->add_child("endDocument");
       
    48 	};
    48 	};
    49 
    49 
    50 	void startSection(const SectionStartEvent& event) override {
    50 	void startSection(const SectionStartEvent& event) override {
    51 		xmlpp::Element* node = domParser->get_document()->get_root_node()->add_child("startSection");
    51 		currentSection = currentSection->add_child(nameCodec.encode(event.name));
    52 		node->add_child("name")->add_child_text(event.name);
    52 		currentSection->set_attribute("type", "section");
    53 		node->add_child("comment")->add_child_text(event.comment);
    53 		currentSection->set_attribute("name", event.name);
    54 		node->add_child("line-number")->add_child_text(std::to_string(event.lineNumber));
    54 		if (event.comment.size()) currentSection->set_attribute("comment", event.comment);
    55 		node->add_child("event-number")->add_child_text(std::to_string(event.eventNumber));
    55 		if (event.lineNumber >= 0) currentSection->set_attribute("line-number", std::to_string(event.lineNumber));
       
    56 		if (event.eventNumber >= 0) currentSection->set_attribute("event-number", std::to_string(event.eventNumber));
    56 	};
    57 	};
    57 
    58 
    58 	void endSection() override {
    59 	void endSection() override {
    59 		domParser->get_document()->get_root_node()->add_child("endSection");
    60 		currentSection = currentSection->get_parent();
       
    61 		if (currentSection == nullptr) throw std::out_of_range("Lunatic INI parser tried to end a section without starting it before.");
    60 	};
    62 	};
    61 
    63 
    62 	void entry(const EntryEvent& event) override {
    64 	void entry(const EntryEvent& event) override {
    63 		xmlpp::Element* node = domParser->get_document()->get_root_node()->add_child("entry");
    65 		xmlpp::Element* entry = currentSection->add_child(nameCodec.encode(event.fullKey));
    64 		node->add_child("key")->add_child_text(event.key);
    66 		entry->set_attribute("type", "entry");
    65 		node->add_child("sub-key")->add_child_text(event.subKey);
    67 		entry->set_attribute("key", event.key);
    66 		node->add_child("full-key")->add_child_text(event.fullKey);
    68 		entry->set_attribute("full-key", event.fullKey);
    67 		node->add_child("value")->add_child_text(event.value);
    69 		if (event.subKey.size()) entry->set_attribute("sub-key", event.subKey);
    68 		node->add_child("comment")->add_child_text(event.comment);
    70 		if (event.comment.size()) currentSection->set_attribute("comment", event.comment);
    69 		node->add_child("line-number")->add_child_text(std::to_string(event.lineNumber));
    71 		if (event.lineNumber >= 0) currentSection->set_attribute("line-number", std::to_string(event.lineNumber));
    70 		node->add_child("event-number")->add_child_text(std::to_string(event.eventNumber));
    72 		if (event.eventNumber >= 0) currentSection->set_attribute("event-number", std::to_string(event.eventNumber));
       
    73 		entry->add_child_text(event.value);
    71 	};
    74 	};
    72 
    75 
    73 };
    76 };
       
    77 
       
    78 // TODO: support also other styles/mappings e.g. <section/> and <entry/> with INI names only in the XML attributes (and thus without @type="section|entry")
    74 
    79 
    75 class XMLDocumentConstructor {
    80 class XMLDocumentConstructor {
    76 private:
    81 private:
    77 	std::istream* input = nullptr;
    82 	std::istream* input = nullptr;
    78 	xmlpp::DomParser* parser = nullptr;
    83 	xmlpp::DomParser* parser = nullptr;