# HG changeset patch # User František Kučera # Date 1606643373 -3600 # Node ID c6527b45fbc20eba9d2ca95d70b577f1720c2c51 # Parent f686bdaeb9e0562283cb465a9d7c23ce14342324 add --parser-option tree-style standard|literal --parser-option tree-with-namespaces true|false diff -r f686bdaeb9e0 -r c6527b45fbc2 bash-completion.sh --- a/bash-completion.sh Sun Nov 29 00:30:36 2020 +0100 +++ b/bash-completion.sh Sun Nov 29 10:49:33 2020 +0100 @@ -73,12 +73,19 @@ "unescape-basic" "unescape-java-properties" "unescape-backspace" + "tree-style" + "tree-with-namespaces" ); DIALECTS=( "java-properties" ); + TREE_STYLES=( + "standard" + "literal" + ) + if [[ "$w1" == "--relation" && "x$w0" == "x" ]]; then COMPREPLY=("''") elif [[ "$w1" == "--records" && "x$w0" == "x" ]]; then COMPREPLY=("'/'") @@ -109,6 +116,8 @@ elif [[ "$w2" == "--parser-option" && "$w1" == "comment-separators" && "x$w0" == "x" ]]; then COMPREPLY=("'#;'") elif [[ "$w2" == "--parser-option" && "$w1" == "key-value-separators" && "x$w0" == "x" ]]; then COMPREPLY=("'=:'") elif [[ "$w2" == "--parser-option" && "$w1" == "quotes" && "x$w0" == "x" ]]; then COMPREPLY=("\$'\"\\''") + elif [[ "$w2" == "--parser-option" && "$w1" == "tree-style" ]]; then COMPREPLY=($(compgen -W "${TREE_STYLES[*]}" -- "$w0")) + elif [[ "$w2" == "--parser-option" && "$w1" == "tree-with-namespaces" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0")) else OPTIONS=( diff -r f686bdaeb9e0 -r c6527b45fbc2 src/XMLDocumentConstructor.h --- 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 reader; + std::shared_ptr handler; public: XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) { @@ -115,15 +148,16 @@ reader->addUnescapingProcessor(std::make_shared(), unescaping::JavaProperties, false); reader->addUnescapingProcessor(std::make_shared(), unescaping::Backspace, true); reader->addDialect(std::make_shared(), dialect::JavaProperties, false); + handler = std::make_shared(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(); } }; diff -r f686bdaeb9e0 -r c6527b45fbc2 src/lib/uri.h --- a/src/lib/uri.h Sun Nov 29 00:30:36 2020 +0100 +++ b/src/lib/uri.h Sun Nov 29 10:49:33 2020 +0100 @@ -44,6 +44,13 @@ static const char* JavaProperties = "java-properties"; } +namespace xml { +static const char* TreeWithNamespaces = "tree-with-namespaces"; +static const char* TreeStyle = "tree-style"; + +static const char* XMLNS = "tag:globalcode.info,2018:alt2xml:TEMPORARY:ini"; // not an option and might change, just preliminary namespace +} + } } }