mirror of
https://github.com/TomWright/dasel.git
synced 2022-05-22 02:32:45 +03:00
Add tests to confirm selecting works with xml
This commit is contained in:
105
README.md
105
README.md
@@ -9,7 +9,7 @@
|
||||
|
||||
Dasel (short for data-selector) allows you to query and modify data structures using selector strings.
|
||||
|
||||
Comparable to [jq](https://github.com/stedolan/jq) / [yq](https://github.com/kislyuk/yq), but supports JSON, YAML and TOML with zero dependencies.
|
||||
Comparable to [jq](https://github.com/stedolan/jq) / [yq](https://github.com/kislyuk/yq), but supports JSON, YAML, TOML and XML with zero runtime dependencies.
|
||||
|
||||
# Table of contents
|
||||
* [Dasel](#dasel)
|
||||
@@ -24,34 +24,35 @@ Comparable to [jq](https://github.com/stedolan/jq) / [yq](https://github.com/kis
|
||||
* [jq to dasel](#jq-to-dasel)
|
||||
* [yq to dasel](#yq-to-dasel)
|
||||
* [Kubernetes](#kubernetes)
|
||||
* [XML](#xml)
|
||||
|
||||
### Installation
|
||||
You can import dasel as a package and use it in your applications, or you can use a pre-built binary to modify files from the command line.
|
||||
|
||||
#### Command line
|
||||
You can `go get` the `main` package and go should automatically build and install dasel for you.
|
||||
```
|
||||
```bash
|
||||
go get github.com/tomwright/dasel/cmd/dasel
|
||||
```
|
||||
|
||||
Alternatively you can download a compiled executable from the [latest release](https://github.com/TomWright/dasel/releases/latest).
|
||||
##### Linux amd64
|
||||
This one liner should work for you - be sure to change the targeted release executable if needed. It currently targets `dasel_linux_amd64`.
|
||||
```
|
||||
```bash
|
||||
curl -s https://api.github.com/repos/tomwright/dasel/releases/latest | grep browser_download_url | grep linux_amd64 | cut -d '"' -f 4 | wget -qi - && mv dasel_linux_amd64 dasel && chmod +x dasel
|
||||
mv ./dasel /usr/local/bin/dasel
|
||||
```
|
||||
|
||||
##### Mac OS amd64
|
||||
You may have to `brew install wget` in order for this to work.
|
||||
```
|
||||
```bash
|
||||
curl -s https://api.github.com/repos/tomwright/dasel/releases/latest | grep browser_download_url | grep macos_amd64 | cut -d '"' -f 4 | wget -qi - && mv dasel_macos_amd64 dasel && chmod +x dasel
|
||||
mv ./dasel /usr/local/bin/dasel
|
||||
```
|
||||
|
||||
#### Import
|
||||
As with any other go package, just use `go get`.
|
||||
```
|
||||
```bash
|
||||
go get github.com/tomwright/dasel
|
||||
```
|
||||
|
||||
@@ -237,9 +238,29 @@ my:
|
||||
## Supported file types
|
||||
Dasel attempts to find the correct parser for the given file type, but if that fails you can choose which parser to use with the `-p` or `--parser` flag.
|
||||
|
||||
- JSON - `-p json`
|
||||
- TOML - `-p toml`
|
||||
- YAML - `-p yaml`
|
||||
### JSON
|
||||
```bash
|
||||
-p json
|
||||
```
|
||||
Using [golang.org/pkg/encoding/json](https://golang.org/pkg/encoding/json/).
|
||||
|
||||
### TOML
|
||||
```bash
|
||||
-p toml
|
||||
```
|
||||
Using [github.com/pelletier/go-toml](https://github.com/pelletier/go-toml).
|
||||
|
||||
### YAML
|
||||
```bash
|
||||
-p yaml
|
||||
```
|
||||
Using [gopkg.in/yaml.v2](https://gopkg.in/yaml.v2).
|
||||
|
||||
### XML
|
||||
```bash
|
||||
-p xml
|
||||
```
|
||||
Using [github.com/clbanning/mxj](https://github.com/clbanning/mxj).
|
||||
|
||||
## Selectors
|
||||
|
||||
@@ -323,7 +344,7 @@ The follow examples show a set of [jq](https://github.com/stedolan/jq) commands
|
||||
|
||||
#### Select a single value
|
||||
|
||||
```
|
||||
```bash
|
||||
echo '{"name": "Tom"}' | jq '.name'
|
||||
"Tom"
|
||||
|
||||
@@ -333,7 +354,7 @@ Tom
|
||||
|
||||
#### Select a nested value
|
||||
|
||||
```
|
||||
```bash
|
||||
echo '{"user": {"name": "Tom", "age": 27}}' | jq '.user.age'
|
||||
27
|
||||
|
||||
@@ -343,7 +364,7 @@ echo '{"user": {"name": "Tom", "age": 27}}' | dasel -p json '.user.age'
|
||||
|
||||
#### Select an array index
|
||||
|
||||
```
|
||||
```bash
|
||||
echo '[1, 2, 3]' | jq '.[1]'
|
||||
2
|
||||
|
||||
@@ -353,7 +374,7 @@ echo '[1, 2, 3]' | dasel -p json '.[1]'
|
||||
|
||||
#### Append to an array of strings
|
||||
|
||||
```
|
||||
```bash
|
||||
echo '["a", "b", "c"]' | jq '. += ["d"]'
|
||||
[
|
||||
"a",
|
||||
@@ -373,7 +394,7 @@ echo '["a", "b", "c"]' | dasel put string -p json -s '.[]' d
|
||||
|
||||
#### Update a string value
|
||||
|
||||
```
|
||||
```bash
|
||||
echo '["a", "b", "c"]' | jq '.[1] = "d"'
|
||||
[
|
||||
"a",
|
||||
@@ -391,7 +412,7 @@ echo '["a", "b", "c"]' | dasel put string -p json -s '.[1]' d
|
||||
|
||||
#### Update an int value
|
||||
|
||||
```
|
||||
```bash
|
||||
echo '[1, 2, 3]' | jq '.[1] = 5'
|
||||
[
|
||||
1,
|
||||
@@ -409,7 +430,7 @@ echo '[1, 2, 3]' | dasel put int -p json -s '.[1]' 5
|
||||
|
||||
#### Overwrite an object
|
||||
|
||||
```
|
||||
```bash
|
||||
echo '{"user": {"name": "Tom", "age": 27}}' | jq '.user = {"name": "Frank", "age": 25}'
|
||||
{
|
||||
"user": {
|
||||
@@ -429,7 +450,7 @@ echo '{"user": {"name": "Tom", "age": 27}}' | dasel put object -p json -s '.user
|
||||
|
||||
#### Append to an array of objects
|
||||
|
||||
```
|
||||
```bash
|
||||
echo '{"users": [{"name": "Tom"}]}' | jq '.users += [{"name": "Frank"}]'
|
||||
{
|
||||
"users": [
|
||||
@@ -461,7 +482,7 @@ The follow examples show a set of [yq](https://github.com/kislyuk/yq) commands a
|
||||
|
||||
#### Select a single value
|
||||
|
||||
```
|
||||
```bash
|
||||
echo 'name: Tom' | yq '.name'
|
||||
"Tom"
|
||||
|
||||
@@ -471,7 +492,7 @@ Tom
|
||||
|
||||
#### Select a nested value
|
||||
|
||||
```
|
||||
```bash
|
||||
echo 'user:
|
||||
name: Tom
|
||||
age: 27' | yq '.user.age'
|
||||
@@ -485,7 +506,7 @@ echo 'user:
|
||||
|
||||
#### Select an array index
|
||||
|
||||
```
|
||||
```bash
|
||||
echo '- 1
|
||||
- 2
|
||||
- 3' | yq '.[1]'
|
||||
@@ -499,7 +520,7 @@ echo '- 1
|
||||
|
||||
#### Append to an array of strings
|
||||
|
||||
```
|
||||
```bash
|
||||
echo '- a
|
||||
- b
|
||||
- c' | yq --yaml-output '. += ["d"]'
|
||||
@@ -520,7 +541,7 @@ echo '- a
|
||||
|
||||
#### Update a string value
|
||||
|
||||
```
|
||||
```bash
|
||||
echo '- a
|
||||
- b
|
||||
- c' | yq --yaml-output '.[1] = "d"'
|
||||
@@ -538,7 +559,7 @@ echo '- a
|
||||
|
||||
#### Update an int value
|
||||
|
||||
```
|
||||
```bash
|
||||
echo '- 1
|
||||
- 2
|
||||
- 3' | yq --yaml-output '.[1] = 5'
|
||||
@@ -556,7 +577,7 @@ echo '- 1
|
||||
|
||||
#### Overwrite an object
|
||||
|
||||
```
|
||||
```bash
|
||||
echo 'user:
|
||||
name: Tom
|
||||
age: 27' | yq --yaml-output '.user = {"name": "Frank", "age": 25}'
|
||||
@@ -575,7 +596,7 @@ user:
|
||||
|
||||
#### Append to an array of objects
|
||||
|
||||
```
|
||||
```bash
|
||||
echo 'users:
|
||||
- name: Tom' | yq --yaml-output '.users += [{"name": "Frank"}]'
|
||||
users:
|
||||
@@ -617,4 +638,40 @@ dasel put object -f deployment.yaml -s "spec.template.spec.containers.(name=auth
|
||||
#### Update an existing env var
|
||||
```bash
|
||||
dasel put string -f deployment.yaml -s "spec.template.spec.containers.(name=auth).env.(name=MY_NEW_ENV_VAR).value" NEW_VALUE
|
||||
```
|
||||
|
||||
### XML
|
||||
|
||||
XML has some slight differences (such as attributes) that should be documented.
|
||||
|
||||
#### Query attributes
|
||||
|
||||
Decoded attributes are set as properties on the related object with a prefix of `-`.
|
||||
|
||||
```bash
|
||||
echo '<data>
|
||||
<users primary="true">
|
||||
<name>Tom</name>
|
||||
</users>
|
||||
<users primary="false">
|
||||
<name>Frank</name>
|
||||
</users>
|
||||
</data>' | go run cmd/dasel/main.go -p xml '.data.users[0].-primary'
|
||||
true
|
||||
```
|
||||
|
||||
#### Filtering on attributes
|
||||
|
||||
We can also filter on attributes since they are defined against the related object.
|
||||
|
||||
```bash
|
||||
echo '<data>
|
||||
<users primary="true">
|
||||
<name>Tom</name>
|
||||
</users>
|
||||
<users primary="false">
|
||||
<name>Frank</name>
|
||||
</users>
|
||||
</data>' | go run cmd/dasel/main.go -p xml '.data.users.(-primary=true).name'
|
||||
Tom
|
||||
```
|
||||
4
go.mod
4
go.mod
@@ -3,10 +3,8 @@ module github.com/tomwright/dasel
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/clbanning/mxj v1.8.5-0.20201012155914-b957cfd48b51
|
||||
github.com/clbanning/mxj/v2 v2.3.2
|
||||
github.com/pelletier/go-toml v1.8.1
|
||||
github.com/spf13/cobra v1.0.0
|
||||
gopkg.in/yaml.v2 v2.2.2
|
||||
)
|
||||
|
||||
replace github.com/clbanning/mxj => /Users/tom/repos/github.com/TomWright/mxj
|
||||
|
||||
4
go.sum
4
go.sum
@@ -7,6 +7,10 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/clbanning/mxj v1.8.5-0.20201012155914-b957cfd48b51 h1:PK4/gQyzsZnkfJdEaWSybHdjsYORx+u34oqN9Sd63Rs=
|
||||
github.com/clbanning/mxj v1.8.5-0.20201012155914-b957cfd48b51/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
|
||||
github.com/clbanning/mxj/v2 v2.3.2 h1:DSkU65zfrBHtrggxd54X9pK1z/Lw2OwSW5D8p+x1toE=
|
||||
github.com/clbanning/mxj/v2 v2.3.2/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
|
||||
@@ -8,6 +8,54 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRootCMD_Put(t *testing.T) {
|
||||
t.Run("String", func(t *testing.T) {
|
||||
t.Run("JSON", putStringTestForParserJSON())
|
||||
t.Run("YAML", putStringTestForParserYAML())
|
||||
t.Run("TOML", putStringTestForParserTOML())
|
||||
|
||||
t.Run("InvalidFile", expectErr(
|
||||
[]string{"put", "string", "-f", "bad.json", "-s", "x", "y"},
|
||||
"could not open input file",
|
||||
))
|
||||
t.Run("MissingParser", expectErr(
|
||||
[]string{"put", "string", "-s", "x", "y"},
|
||||
"parser flag required when reading from stdin",
|
||||
))
|
||||
t.Run("StdinStdout", expectOutput(
|
||||
`{"name": "Tom"}`,
|
||||
[]string{"put", "string", "-f", "stdin", "-o", "stdout", "-p", "json", "-s", ".name", "Frank"},
|
||||
`{
|
||||
"name": "Frank"
|
||||
}
|
||||
`,
|
||||
))
|
||||
t.Run("StdinStdoutAlias", expectOutput(
|
||||
`{"name": "Tom"}`,
|
||||
[]string{"put", "string", "-f", "-", "-o", "-", "-p", "json", "-s", ".name", "Frank"},
|
||||
`{
|
||||
"name": "Frank"
|
||||
}
|
||||
`,
|
||||
))
|
||||
})
|
||||
t.Run("Int", func(t *testing.T) {
|
||||
t.Run("JSON", putIntTestForParserJSON())
|
||||
t.Run("YAML", putIntTestForParserYAML())
|
||||
t.Run("TOML", putIntTestForParserTOML())
|
||||
})
|
||||
t.Run("Bool", func(t *testing.T) {
|
||||
t.Run("JSON", putBoolTestForParserJSON())
|
||||
t.Run("YAML", putBoolTestForParserYAML())
|
||||
t.Run("TOML", putBoolTestForParserTOML())
|
||||
})
|
||||
t.Run("Object", func(t *testing.T) {
|
||||
t.Run("JSON", putObjectTestForParserJSON())
|
||||
t.Run("YAML", putObjectTestForParserYAML())
|
||||
t.Run("TOML", putObjectTestForParserTOML())
|
||||
})
|
||||
}
|
||||
|
||||
func putTest(in string, varType string, parser string, selector string, value string, out string, expErr error, additionalArgs ...string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
cmd := command.NewRootCMD()
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
var jsonDataSingle = `{"x": "asd"}`
|
||||
var yamlDataSingle = `x: asd`
|
||||
var tomlDataSingle = `x="asd"`
|
||||
var xmlDataSingle = `<x>asd</x>`
|
||||
|
||||
var jsonData = `{
|
||||
"id": "1111",
|
||||
@@ -69,6 +70,53 @@ var tomlData = `id = "1111"
|
||||
postcode = "YYY YYY"
|
||||
`
|
||||
|
||||
var xmlData = `<data>
|
||||
<id>1111</id>
|
||||
<details>
|
||||
<name>Tom</name>
|
||||
<age>27</age>
|
||||
<addresses primary="true">
|
||||
<street>101 Some Street</street>
|
||||
<town>Some Town</town>
|
||||
<county>Some County</county>
|
||||
<postcode>XXX XXX</postcode>
|
||||
</addresses>
|
||||
<addresses>
|
||||
<street>34 Another Street</street>
|
||||
<town>Another Town</town>
|
||||
<county>Another County</county>
|
||||
<postcode>YYY YYY</postcode>
|
||||
</addresses>
|
||||
</details>
|
||||
</data>
|
||||
`
|
||||
|
||||
func TestRootCMD_Select(t *testing.T) {
|
||||
t.Run("JSON", selectTestForParser("json", jsonData, jsonDataSingle))
|
||||
t.Run("YAML", selectTestForParser("yaml", yamlData, yamlDataSingle))
|
||||
t.Run("TOML", selectTestForParser("toml", tomlData, tomlDataSingle))
|
||||
t.Run("InvalidFile", expectErr(
|
||||
[]string{"select", "-f", "bad.json", "-s", "x"},
|
||||
"could not open input file",
|
||||
))
|
||||
t.Run("MissingParser", expectErr(
|
||||
[]string{"select", "-s", "x"},
|
||||
"parser flag required when reading from stdin",
|
||||
))
|
||||
t.Run("Stdin", expectOutput(
|
||||
`{"name": "Tom"}`,
|
||||
[]string{"select", "-f", "stdin", "-p", "json", "-s", ".name"},
|
||||
`Tom
|
||||
`,
|
||||
))
|
||||
t.Run("StdinAlias", expectOutput(
|
||||
`{"name": "Tom"}`,
|
||||
[]string{"select", "-f", "-", "-p", "json", "-s", ".name"},
|
||||
`Tom
|
||||
`,
|
||||
))
|
||||
}
|
||||
|
||||
func selectTest(in string, parser string, selector string, out string, expErr error) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
cmd := command.NewRootCMD()
|
||||
@@ -148,6 +196,17 @@ func selectTestFromFile(inputPath string, selector string, out string, expErr er
|
||||
}
|
||||
}
|
||||
|
||||
func TestRootCMD_Select_XML(t *testing.T) {
|
||||
t.Run("RootElement", selectTest(xmlDataSingle, "xml", ".", "map[x:asd]\n", nil))
|
||||
t.Run("SingleProperty", selectTest(xmlData, "xml", ".data.id", "1111\n", nil))
|
||||
t.Run("ObjectProperty", selectTest(xmlData, "xml", ".data.details.name", "Tom\n", nil))
|
||||
t.Run("Index", selectTest(xmlData, "xml", ".data.details.addresses.[0].street", "101 Some Street\n", nil))
|
||||
t.Run("Index", selectTest(xmlData, "xml", ".data.details.addresses.[1].street", "34 Another Street\n", nil))
|
||||
t.Run("DynamicString", selectTest(xmlData, "xml", ".data.details.addresses.(postcode=XXX XXX).street", "101 Some Street\n", nil))
|
||||
t.Run("DynamicString", selectTest(xmlData, "xml", ".data.details.addresses.(postcode=YYY YYY).street", "34 Another Street\n", nil))
|
||||
t.Run("Attribute", selectTest(xmlData, "xml", ".data.details.addresses.(-primary=true).street", "101 Some Street\n", nil))
|
||||
}
|
||||
|
||||
func selectTestForParser(parser string, data string, singleData string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Run("RootElement", selectTest(singleData, parser, ".", "map[x:asd]\n", nil))
|
||||
|
||||
@@ -45,114 +45,42 @@ func TestChangeDefaultCommand(t *testing.T) {
|
||||
))
|
||||
}
|
||||
|
||||
func TestRootCMD(t *testing.T) {
|
||||
expectErr := func(args []string, expErr string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
cmd := command.NewRootCMD()
|
||||
outputBuffer := bytes.NewBuffer([]byte{})
|
||||
func expectErr(args []string, expErr string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
cmd := command.NewRootCMD()
|
||||
outputBuffer := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd.SetOut(outputBuffer)
|
||||
cmd.SetArgs(args)
|
||||
cmd.SetOut(outputBuffer)
|
||||
cmd.SetArgs(args)
|
||||
|
||||
err := cmd.Execute()
|
||||
err := cmd.Execute()
|
||||
|
||||
if err == nil || !strings.Contains(err.Error(), expErr) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
if err == nil || !strings.Contains(err.Error(), expErr) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
expectOutput := func(in string, args []string, exp string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
cmd := command.NewRootCMD()
|
||||
outputBuffer := bytes.NewBuffer([]byte{})
|
||||
}
|
||||
|
||||
cmd.SetIn(bytes.NewReader([]byte(in)))
|
||||
cmd.SetOut(outputBuffer)
|
||||
cmd.SetArgs(args)
|
||||
func expectOutput(in string, args []string, exp string) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
cmd := command.NewRootCMD()
|
||||
outputBuffer := bytes.NewBuffer([]byte{})
|
||||
|
||||
err := cmd.Execute()
|
||||
cmd.SetIn(bytes.NewReader([]byte(in)))
|
||||
cmd.SetOut(outputBuffer)
|
||||
cmd.SetArgs(args)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
err := cmd.Execute()
|
||||
|
||||
got := outputBuffer.String()
|
||||
if exp != got {
|
||||
t.Errorf("expected %s, got %s", exp, got)
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
got := outputBuffer.String()
|
||||
if exp != got {
|
||||
t.Errorf("expected %s, got %s", exp, got)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("Select", func(t *testing.T) {
|
||||
t.Run("JSON", selectTestForParser("json", jsonData, jsonDataSingle))
|
||||
t.Run("YAML", selectTestForParser("yaml", yamlData, yamlDataSingle))
|
||||
t.Run("TOML", selectTestForParser("toml", tomlData, tomlDataSingle))
|
||||
t.Run("InvalidFile", expectErr(
|
||||
[]string{"select", "-f", "bad.json", "-s", "x"},
|
||||
"could not open input file",
|
||||
))
|
||||
t.Run("MissingParser", expectErr(
|
||||
[]string{"select", "-s", "x"},
|
||||
"parser flag required when reading from stdin",
|
||||
))
|
||||
t.Run("Stdin", expectOutput(
|
||||
`{"name": "Tom"}`,
|
||||
[]string{"select", "-f", "stdin", "-p", "json", "-s", ".name"},
|
||||
`Tom
|
||||
`,
|
||||
))
|
||||
t.Run("StdinAlias", expectOutput(
|
||||
`{"name": "Tom"}`,
|
||||
[]string{"select", "-f", "-", "-p", "json", "-s", ".name"},
|
||||
`Tom
|
||||
`,
|
||||
))
|
||||
})
|
||||
t.Run("PutString", func(t *testing.T) {
|
||||
t.Run("JSON", putStringTestForParserJSON())
|
||||
t.Run("YAML", putStringTestForParserYAML())
|
||||
t.Run("TOML", putStringTestForParserTOML())
|
||||
|
||||
t.Run("InvalidFile", expectErr(
|
||||
[]string{"put", "string", "-f", "bad.json", "-s", "x", "y"},
|
||||
"could not open input file",
|
||||
))
|
||||
t.Run("MissingParser", expectErr(
|
||||
[]string{"put", "string", "-s", "x", "y"},
|
||||
"parser flag required when reading from stdin",
|
||||
))
|
||||
t.Run("StdinStdout", expectOutput(
|
||||
`{"name": "Tom"}`,
|
||||
[]string{"put", "string", "-f", "stdin", "-o", "stdout", "-p", "json", "-s", ".name", "Frank"},
|
||||
`{
|
||||
"name": "Frank"
|
||||
}
|
||||
`,
|
||||
))
|
||||
t.Run("StdinStdoutAlias", expectOutput(
|
||||
`{"name": "Tom"}`,
|
||||
[]string{"put", "string", "-f", "-", "-o", "-", "-p", "json", "-s", ".name", "Frank"},
|
||||
`{
|
||||
"name": "Frank"
|
||||
}
|
||||
`,
|
||||
))
|
||||
})
|
||||
t.Run("PutInt", func(t *testing.T) {
|
||||
t.Run("JSON", putIntTestForParserJSON())
|
||||
t.Run("YAML", putIntTestForParserYAML())
|
||||
t.Run("TOML", putIntTestForParserTOML())
|
||||
})
|
||||
t.Run("PutBool", func(t *testing.T) {
|
||||
t.Run("JSON", putBoolTestForParserJSON())
|
||||
t.Run("YAML", putBoolTestForParserYAML())
|
||||
t.Run("TOML", putBoolTestForParserTOML())
|
||||
})
|
||||
t.Run("PutObject", func(t *testing.T) {
|
||||
t.Run("JSON", putObjectTestForParserJSON())
|
||||
t.Run("YAML", putObjectTestForParserYAML())
|
||||
t.Run("TOML", putObjectTestForParserTOML())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ func NewParserFromFilename(filename string) (Parser, error) {
|
||||
return &TOMLParser{}, nil
|
||||
case ".json":
|
||||
return &JSONParser{}, nil
|
||||
case ".xml":
|
||||
return &XMLParser{}, nil
|
||||
default:
|
||||
return nil, &UnknownParserErr{Parser: ext}
|
||||
}
|
||||
@@ -51,6 +53,8 @@ func NewParserFromString(parser string) (Parser, error) {
|
||||
return &JSONParser{}, nil
|
||||
case "toml":
|
||||
return &TOMLParser{}, nil
|
||||
case "xml":
|
||||
return &XMLParser{}, nil
|
||||
default:
|
||||
return nil, &UnknownParserErr{Parser: parser}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/clbanning/mxj"
|
||||
"github.com/clbanning/mxj/v2"
|
||||
)
|
||||
|
||||
// XMLParser is a Parser implementation to handle yaml files.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package storage_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/tomwright/dasel/internal/storage"
|
||||
"reflect"
|
||||
"testing"
|
||||
@@ -15,6 +16,21 @@ var xmlMap = map[string]interface{}{
|
||||
},
|
||||
}
|
||||
|
||||
func TestXMLParser_FromBytes2(t *testing.T) {
|
||||
got, err := (&storage.XMLParser{}).FromBytes([]byte(`<data>
|
||||
<names>
|
||||
<name>Tom</name>
|
||||
<name>Jim</name>
|
||||
</names>
|
||||
</data>`))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println(got)
|
||||
}
|
||||
|
||||
func TestXMLParser_FromBytes(t *testing.T) {
|
||||
got, err := (&storage.XMLParser{}).FromBytes(xmlBytes)
|
||||
if err != nil {
|
||||
|
||||
21
tests/assets/example.xml
Normal file
21
tests/assets/example.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<data>
|
||||
<name>Tom</name>
|
||||
<preferences>
|
||||
<favouriteColour>red</favouriteColour>
|
||||
</preferences>
|
||||
<colours>red</colours>
|
||||
<colours>green</colours>
|
||||
<colours>blue</colours>
|
||||
<colourCodes>
|
||||
<name>red</name>
|
||||
<rgb>ff0000</rgb>
|
||||
</colourCodes>
|
||||
<colourCodes>
|
||||
<name>green</name>
|
||||
<rgb>00ff00</rgb>
|
||||
</colourCodes>
|
||||
<colourCodes>
|
||||
<name>blue</name>
|
||||
<rgb>0000ff</rgb>
|
||||
</colourCodes>
|
||||
</data>
|
||||
Reference in New Issue
Block a user