add --parser-option tree-style standard|literal --parser-option tree-with-namespaces true|false
--- 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=(
--- 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();
}
};
--- 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
+}
+
}
}
}