--- a/bash-completion.sh Sat Nov 28 21:09:18 2020 +0100
+++ b/bash-completion.sh Sun Nov 29 00:30:36 2020 +0100
@@ -28,7 +28,7 @@
"boolean"
)
- XINCLUDE=(
+ BOOLEAN_VALUES=(
"true"
"false"
)
@@ -59,6 +59,26 @@
"http://docbook.org/ns/docbook"
)
+ # TODO: introspection: after moving to alt2xml the available options and their values should be provided by the parser
+
+ PARSER_OPTIONS=(
+ "trim-continuing-lines"
+ "allow-sections"
+ "allow-section-tags"
+ "allow-sub-keys"
+ "comment-separators"
+ "key-value-separators"
+ "quotes"
+ "dialect"
+ "unescape-basic"
+ "unescape-java-properties"
+ "unescape-backspace"
+ );
+
+ DIALECTS=(
+ "java-properties"
+ );
+
if [[ "$w1" == "--relation" && "x$w0" == "x" ]]; then COMPREPLY=("''")
elif [[ "$w1" == "--records" && "x$w0" == "x" ]]; then COMPREPLY=("'/'")
@@ -67,7 +87,7 @@
elif [[ "$w3" == "--attribute" && "x$w0" == "x" ]]; then COMPREPLY=("''")
elif [[ "$w1" == "--namespace" && "x$w0" == "x" ]]; then COMPREPLY=("''")
elif [[ "$w2" == "--namespace" ]]; then COMPREPLY=($(compgen -W "${XMLNS[*]}" -- "$w0"))
- elif [[ "$w1" == "--xinclude" ]]; then COMPREPLY=($(compgen -W "${XINCLUDE[*]}" -- "$w0"))
+ elif [[ "$w1" == "--xinclude" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
elif [[ "$w1" == "--mode" ]]; then COMPREPLY=($(compgen -W "${MODE[*]}" -- "$w0"))
elif [[ "$w1" == "--raw-xml-nodelist-wrapper" ]]; then COMPREPLY=("'xml'")
elif [[ "$w2" == "--raw-xml-nodelist-wrapper" && "x$w0" == "x" ]]; then COMPREPLY=("''")
@@ -76,9 +96,24 @@
elif [[ "$w1" == "--raw-xml-attribute-wrapper" ]]; then COMPREPLY=("'attribute'")
elif [[ "$w2" == "--raw-xml-attribute-wrapper" && "x$w0" == "x" ]]; then COMPREPLY=("''")
elif [[ "$w3" == "--raw-xml-attribute-wrapper" && "x$w0" == "x" ]]; then COMPREPLY=("''")
+
+ elif [[ "$w1" == "--parser-option" ]]; then COMPREPLY=($(compgen -W "${PARSER_OPTIONS[*]}" -- "$w0"))
+ elif [[ "$w2" == "--parser-option" && "$w1" == "trim-continuing-lines" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
+ elif [[ "$w2" == "--parser-option" && "$w1" == "allow-sections" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
+ elif [[ "$w2" == "--parser-option" && "$w1" == "allow-section-tags" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
+ elif [[ "$w2" == "--parser-option" && "$w1" == "allow-sub-keys" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
+ elif [[ "$w2" == "--parser-option" && "$w1" == "unescape-basic" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
+ elif [[ "$w2" == "--parser-option" && "$w1" == "unescape-java-properties" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
+ elif [[ "$w2" == "--parser-option" && "$w1" == "unescape-backspace" ]]; then COMPREPLY=($(compgen -W "${BOOLEAN_VALUES[*]}" -- "$w0"))
+ elif [[ "$w2" == "--parser-option" && "$w1" == "dialect" ]]; then COMPREPLY=($(compgen -W "${DIALECTS[*]}" -- "$w0"))
+ 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=("\$'\"\\''")
+
else
OPTIONS=(
"--namespace"
+ "--parser-option"
"--relation"
"--records"
"--name-is-xpath"
--- a/src/CLIParser.h Sat Nov 28 21:09:18 2020 +0100
+++ b/src/CLIParser.h Sun Nov 29 00:30:36 2020 +0100
@@ -63,6 +63,7 @@
public:
static const string_t OPTION_NAMESPACE;
+ static const string_t OPTION_PARSER_OPTION;
static const string_t OPTION_RELATION;
static const string_t OPTION_NAME_IS_XPATH;
static const string_t OPTION_RECORDS;
@@ -82,6 +83,8 @@
if (option == OPTION_NAMESPACE) {
c.namespaceMappings.push_back(readNext(arguments, i));
c.namespaceMappings.push_back(readNext(arguments, i));
+ } else if (option == OPTION_PARSER_OPTION) {
+ c.parserOptions.push_back({readNext(arguments, i), readNext(arguments, i)});
} else if (option == OPTION_XINCLUDE) {
c.xinclude = parseBoolean(readNext(arguments, i));
} else if (option == OPTION_RELATION) {
@@ -131,6 +134,7 @@
};
const string_t CLIParser::OPTION_NAMESPACE = L"--namespace";
+const string_t CLIParser::OPTION_PARSER_OPTION = L"--parser-option";
const string_t CLIParser::OPTION_RELATION = L"--relation";
const string_t CLIParser::OPTION_NAME_IS_XPATH = L"--name-is-xpath";
const string_t CLIParser::OPTION_RECORDS = L"--records";
--- a/src/Configuration.h Sat Nov 28 21:09:18 2020 +0100
+++ b/src/Configuration.h Sun Nov 29 00:30:36 2020 +0100
@@ -65,6 +65,15 @@
};
+class ParserOptionRecipe {
+public:
+ relpipe::writer::string_t uri;
+ relpipe::writer::string_t value;
+
+ ParserOptionRecipe(relpipe::writer::string_t uri, relpipe::writer::string_t value) : uri(uri), value(value) {
+ }
+};
+
class RelationConfiguration {
public:
@@ -86,6 +95,7 @@
public:
std::vector<RelationConfiguration> relationConfigurations;
std::vector<relpipe::writer::string_t> namespaceMappings;
+ std::vector<ParserOptionRecipe> parserOptions;
bool xinclude = false;
virtual ~Configuration() {
@@ -94,4 +104,4 @@
}
}
-}
\ No newline at end of file
+}
--- a/src/XMLDocumentConstructor.h Sat Nov 28 21:09:18 2020 +0100
+++ b/src/XMLDocumentConstructor.h Sun Nov 29 00:30:36 2020 +0100
@@ -106,22 +106,24 @@
private:
std::istream* input = nullptr;
xmlpp::DomParser* parser = nullptr;
+ std::shared_ptr<INIReader> reader;
public:
XMLDocumentConstructor(std::istream* input, xmlpp::DomParser* parser) : input(input), parser(parser) {
+ reader.reset(INIReader::create(*input));
+ reader->addUnescapingProcessor(std::make_shared<BasicUnescapingProcessor>(), unescaping::Basic, true);
+ 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);
+ }
+
+ void setOption(const std::string& uri, const std::string& value) {
+ reader->setOption(uri, value);
}
void process() {
HierarchicalINIContentHandler handler(parser);
- std::shared_ptr<INIReader> reader(INIReader::create(*input));
- reader->addUnescapingProcessor(std::make_shared<BasicUnescapingProcessor>(), unescaping::Basic, true);
- 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);
reader->addHandler(&handler);
- // TODO: smart pointers vs. references: are we going to call addUnescapingProcessor() dynamically/conditionally or share instances? Then pointers will be better.
- // TODO: call setOption() according to the configuration
- // for (ParserOptionRecipe option : configuration.parserOptions) reader->setOption(convertor.to_bytes(option.uri), convertor.to_bytes(option.value));
reader->process();
}
};
--- a/src/XMLTableCommand.h Sat Nov 28 21:09:18 2020 +0100
+++ b/src/XMLTableCommand.h Sun Nov 29 00:30:36 2020 +0100
@@ -88,6 +88,7 @@
xmlpp::DomParser parser;
XMLDocumentConstructor documentConstructor(&input, &parser);
+ for (ParserOptionRecipe o : configuration.parserOptions) documentConstructor.setOption(convertor.to_bytes(o.uri), convertor.to_bytes(o.value));
documentConstructor.process();
if (configuration.xinclude) parser.get_document()->process_xinclude(true);
xmlpp::Element* root = parser.get_document()->get_root_node();