From 75fffc17e1780db525caa0960103484ebf9c50cd Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Tue, 15 Feb 2022 14:51:22 +1100 Subject: [PATCH] Added support for load_props, added missing load_xml tests --- examples/small.properties | 1 + examples/small.xml | 1 + pkg/yqlib/doc/operators/headers/load.md | 22 ++++++- pkg/yqlib/doc/operators/load.md | 77 ++++++++++++++++++++++++- pkg/yqlib/expression_tokeniser.go | 3 + pkg/yqlib/operator_load_test.go | 27 ++++++++- 6 files changed, 125 insertions(+), 6 deletions(-) create mode 100644 examples/small.properties create mode 100644 examples/small.xml diff --git a/examples/small.properties b/examples/small.properties new file mode 100644 index 0000000..7a75a2e --- /dev/null +++ b/examples/small.properties @@ -0,0 +1 @@ +this.is = a properties file \ No newline at end of file diff --git a/examples/small.xml b/examples/small.xml new file mode 100644 index 0000000..8bec459 --- /dev/null +++ b/examples/small.xml @@ -0,0 +1 @@ +is some xml \ No newline at end of file diff --git a/pkg/yqlib/doc/operators/headers/load.md b/pkg/yqlib/doc/operators/headers/load.md index 2e6fc46..7d9e1a2 100644 --- a/pkg/yqlib/doc/operators/headers/load.md +++ b/pkg/yqlib/doc/operators/headers/load.md @@ -1,10 +1,17 @@ # Load -The `load`/`strload` operator allows you to load in content from another file referenced in your yaml document. +The load operators allows you to load in content from another file. Note that you can use string operators like `+` and `sub` to modify the value in the yaml file to a path that exists in your system. -Use `strload` to load text based content as a string block, and `load` to interpret the file as yaml. +You can load files of the following supported types: + +|Format | Load Operator | +| --- | --- | +| Yaml | load | +| XML | load_xml | +| Properties | load_props | +| Plain String | load_str | Lets say there is a file `../../examples/thing.yml`: @@ -12,3 +19,14 @@ Lets say there is a file `../../examples/thing.yml`: a: apple is included b: cool ``` +and a file `small.xml`: + +```xml +is some xml +``` + +and `small.properties`: + +```properties +this.is = a properties file +``` diff --git a/pkg/yqlib/doc/operators/load.md b/pkg/yqlib/doc/operators/load.md index 8f37566..a74534f 100644 --- a/pkg/yqlib/doc/operators/load.md +++ b/pkg/yqlib/doc/operators/load.md @@ -1,10 +1,17 @@ # Load -The `load`/`strload` operator allows you to load in content from another file referenced in your yaml document. +The load operators allows you to load in content from another file. Note that you can use string operators like `+` and `sub` to modify the value in the yaml file to a path that exists in your system. -Use `strload` to load text based content as a string block, and `load` to interpret the file as yaml. +You can load files of the following supported types: + +|Format | Load Operator | +| --- | --- | +| Yaml | load | +| XML | load_xml | +| Properties | load_props | +| Plain String | load_str | Lets say there is a file `../../examples/thing.yml`: @@ -12,6 +19,17 @@ Lets say there is a file `../../examples/thing.yml`: a: apple is included b: cool ``` +and a file `small.xml`: + +```xml +is some xml +``` + +and `small.properties`: + +```properties +this.is = a properties file +``` {% hint style="warning" %} Note that versions prior to 4.18 require the 'eval/e' command to be specified. @@ -89,7 +107,7 @@ something: ``` then ```bash -yq '.something |= strload("../../examples/" + .file)' sample.yml +yq '.something |= load_str("../../examples/" + .file)' sample.yml ``` will output ```yaml @@ -98,3 +116,56 @@ something: |- b: cool. ``` +## Load from XML +Given a sample.yml file of: +```yaml +cool: things +``` +then +```bash +yq '.more_stuff = load_xml("../../examples/small.xml")' sample.yml +``` +will output +```yaml +cool: things +more_stuff: + this: is some xml +``` + +## Load from Properties +Given a sample.yml file of: +```yaml +cool: things +``` +then +```bash +yq '.more_stuff = load_props("../../examples/small.properties")' sample.yml +``` +will output +```yaml +cool: things +more_stuff: + this: + is: a properties file +``` + +## Merge from properties +This can be used as a convenient way to update a yaml document + +Given a sample.yml file of: +```yaml +this: + is: from yaml + cool: ay +``` +then +```bash +yq '. *= load_props("../../examples/small.properties")' sample.yml +``` +will output +```yaml +this: + is: a properties file + cool: ay +``` + diff --git a/pkg/yqlib/expression_tokeniser.go b/pkg/yqlib/expression_tokeniser.go index 0c8d962..8e94264 100644 --- a/pkg/yqlib/expression_tokeniser.go +++ b/pkg/yqlib/expression_tokeniser.go @@ -380,6 +380,9 @@ func initLexer() (*lex.Lexer, error) { lexer.Add([]byte(`load_xml`), opTokenWithPrefs(loadOpType, nil, loadPrefs{loadAsString: false, decoder: NewXMLDecoder(XMLPreferences.AttributePrefix, XMLPreferences.ContentName)})) lexer.Add([]byte(`loadxml`), opTokenWithPrefs(loadOpType, nil, loadPrefs{loadAsString: false, decoder: NewXMLDecoder(XMLPreferences.AttributePrefix, XMLPreferences.ContentName)})) + lexer.Add([]byte(`load_props`), opTokenWithPrefs(loadOpType, nil, loadPrefs{loadAsString: false, decoder: NewPropertiesDecoder()})) + lexer.Add([]byte(`loadprops`), opTokenWithPrefs(loadOpType, nil, loadPrefs{loadAsString: false, decoder: NewPropertiesDecoder()})) + lexer.Add([]byte(`strload`), opTokenWithPrefs(loadOpType, nil, loadPrefs{loadAsString: true})) lexer.Add([]byte(`load_str`), opTokenWithPrefs(loadOpType, nil, loadPrefs{loadAsString: true})) lexer.Add([]byte(`loadstr`), opTokenWithPrefs(loadOpType, nil, loadPrefs{loadAsString: true})) diff --git a/pkg/yqlib/operator_load_test.go b/pkg/yqlib/operator_load_test.go index 5cfae4a..a735d27 100644 --- a/pkg/yqlib/operator_load_test.go +++ b/pkg/yqlib/operator_load_test.go @@ -35,11 +35,36 @@ var loadScenarios = []expressionScenario{ description: "Replace node with referenced file as string", subdescription: "This will work for any text based file", document: `{something: {file: "thing.yml"}}`, - expression: `.something |= strload("../../examples/" + .file)`, + expression: `.something |= load_str("../../examples/" + .file)`, expected: []string{ "D0, P[], (doc)::{something: \"a: apple is included\\nb: cool.\"}\n", }, }, + { + description: "Load from XML", + document: "cool: things", + expression: `.more_stuff = load_xml("../../examples/small.xml")`, + expected: []string{ + "D0, P[], (doc)::cool: things\nmore_stuff:\n this: is some xml\n", + }, + }, + { + description: "Load from Properties", + document: "cool: things", + expression: `.more_stuff = load_props("../../examples/small.properties")`, + expected: []string{ + "D0, P[], (doc)::cool: things\nmore_stuff:\n this:\n is: a properties file\n", + }, + }, + { + description: "Merge from properties", + subdescription: "This can be used as a convenient way to update a yaml document", + document: "this:\n is: from yaml\n cool: ay\n", + expression: `. *= load_props("../../examples/small.properties")`, + expected: []string{ + "D0, P[], (!!map)::this:\n is: a properties file\n cool: ay\n", + }, + }, } func TestLoadScenarios(t *testing.T) {