This commit is contained in:
Mike Farah 2022-10-23 14:48:57 +11:00
parent 55383b9ce1
commit cb86ec94ff
3 changed files with 76 additions and 25 deletions

View File

@ -4,4 +4,29 @@ Encode and decode to and from XML. Whitespace is not conserved for round trips -
Consecutive xml nodes with the same name are assumed to be arrays. Consecutive xml nodes with the same name are assumed to be arrays.
XML content data and attributes are created as fields. This can be controlled by the `'--xml-attribute-prefix` and `--xml-content-name` flags - see below for examples. XML content data, attributes processing instructions and directives are all created as plain fields.
This can be controlled by:
| Flag | Default |Sample XML |
| -- | -- | -- |
| `--xml-attribute-prefix` | `+` (changing to `+@` soon) | Legs in ```<cat legs="4"/>``` |
| `--xml-content-name` | `+content` | Meow in ```<cat>Meow <fur>true</true></cat>``` |
| `--xml-directive-name` | `+directive` | ```<!DOCTYPE config system "blah">``` |
| `--xml-proc-inst-prefix` | `+p_` | ```<?xml version="1"?>``` |
## Encoder / Decoder flag options
In addition to the above flags, there are the following xml encoder/decoder options controlled by flags:
| Flag | Default | Description |
| -- | -- | -- |
| `--xml-strict-mode` | false | Strict mode enforces the requirements of the XML specification. When switched off the parser allows input containing common mistakes. See [the Golang xml decoder ](https://pkg.go.dev/encoding/xml#Decoder) for more details.|
| `--xml-keep-namespace` | true | Keeps the namespace of attributes |
| `--xml-raw-token` | true | Does not verify that start and end elements match and does not translate name space prefixes to their corresponding URLs. |
| `--xml-skip-proc-inst` | false | Skips over processing instructions, e.g. `<?xml version="1"?>` |
| `--xml-skip-directives` | false | Skips over directives, e.g. ```<!DOCTYPE config system "blah">``` |
See below for examples

View File

@ -4,7 +4,32 @@ Encode and decode to and from XML. Whitespace is not conserved for round trips -
Consecutive xml nodes with the same name are assumed to be arrays. Consecutive xml nodes with the same name are assumed to be arrays.
XML content data and attributes are created as fields. This can be controlled by the `'--xml-attribute-prefix` and `--xml-content-name` flags - see below for examples. XML content data, attributes processing instructions and directives are all created as plain fields.
This can be controlled by:
| Flag | Default |Sample XML |
| -- | -- | -- |
| `--xml-attribute-prefix` | `+` (changing to `+@` soon) | Legs in ```<cat legs="4"/>``` |
| `--xml-content-name` | `+content` | Meow in ```<cat>Meow <fur>true</true></cat>``` |
| `--xml-directive-name` | `+directive` | ```<!DOCTYPE config system "blah">``` |
| `--xml-proc-inst-prefix` | `+p_` | ```<?xml version="1"?>``` |
## Encoder / Decoder flag options
In addition to the above flags, there are the following xml encoder/decoder options controlled by flags:
| Flag | Default | Description |
| -- | -- | -- |
| `--xml-strict-mode` | false | Strict mode enforces the requirements of the XML specification. When switched off the parser allows input containing common mistakes. See [the Golang xml decoder ](https://pkg.go.dev/encoding/xml#Decoder) for more details.|
| `--xml-keep-namespace` | true | Keeps the namespace of attributes |
| `--xml-raw-token` | true | Does not verify that start and end elements match and does not translate name space prefixes to their corresponding URLs. |
| `--xml-skip-proc-inst` | false | Skips over processing instructions, e.g. `<?xml version="1"?>` |
| `--xml-skip-directives` | false | Skips over directives, e.g. ```<!DOCTYPE config system "blah">``` |
See below for examples
{% hint style="warning" %} {% hint style="warning" %}
Note that versions prior to 4.18 require the 'eval/e' command to be specified.&#x20; Note that versions prior to 4.18 require the 'eval/e' command to be specified.&#x20;
@ -101,7 +126,7 @@ will output
```yaml ```yaml
+p_xml: version="1.0" encoding="UTF-8" +p_xml: version="1.0" encoding="UTF-8"
cat: cat:
+@legs: "4" +legs: "4"
legs: "7" legs: "7"
``` ```
@ -122,7 +147,7 @@ will output
+p_xml: version="1.0" encoding="UTF-8" +p_xml: version="1.0" encoding="UTF-8"
cat: cat:
+content: meow +content: meow
+@legs: "4" +legs: "4"
``` ```
## Parse xml: custom dtd ## Parse xml: custom dtd
@ -320,7 +345,7 @@ Fields with the matching xml-attribute-prefix are assumed to be attributes.
Given a sample.yml file of: Given a sample.yml file of:
```yaml ```yaml
cat: cat:
+@name: tiger +name: tiger
meows: true meows: true
``` ```
@ -341,7 +366,7 @@ Fields with the matching xml-content-name is assumed to be content.
Given a sample.yml file of: Given a sample.yml file of:
```yaml ```yaml
cat: cat:
+@name: tiger +name: tiger
+content: cool +content: cool
``` ```

View File

@ -58,7 +58,7 @@ cat:
d: d:
# in d before # in d before
z: z:
+@sweet: cool +sweet: cool
# in d after # in d after
# in y after # in y after
# in_cat_after # in_cat_after
@ -98,11 +98,11 @@ cat:
d: d:
- # in d before - # in d before
z: z:
+@sweet: cool +sweet: cool
# in d after # in d after
- # in d2 before - # in d2 before
z: z:
+@sweet: cool2 +sweet: cool2
# in d2 after # in d2 after
# in y after # in y after
# in_cat_after # in_cat_after
@ -161,16 +161,16 @@ const inputXMLWithNamespacedAttr = `
const expectedYAMLWithNamespacedAttr = `+p_xml: version="1.0" const expectedYAMLWithNamespacedAttr = `+p_xml: version="1.0"
map: map:
+@xmlns: some-namespace +xmlns: some-namespace
+@xmlns:xsi: some-instance +xmlns:xsi: some-instance
+@some-instance:schemaLocation: some-url +some-instance:schemaLocation: some-url
` `
const expectedYAMLWithRawNamespacedAttr = `+p_xml: version="1.0" const expectedYAMLWithRawNamespacedAttr = `+p_xml: version="1.0"
map: map:
+@xmlns: some-namespace +xmlns: some-namespace
+@xmlns:xsi: some-instance +xmlns:xsi: some-instance
+@xsi:schemaLocation: some-url +xsi:schemaLocation: some-url
` `
const xmlWithCustomDtd = ` const xmlWithCustomDtd = `
@ -193,8 +193,9 @@ const expectedDtd = `<?xml version="1.0"?>
</root> </root>
` `
const expectedSkippedDtd = `<root> const expectedSkippedDtd = `<?xml version="1.0"?>
<item>&writer;&copyright;</item> <root>
<item>&amp;writer;&amp;copyright;</item>
</root> </root>
` `
@ -227,32 +228,32 @@ var xmlScenarios = []formatScenario{
description: "Parse xml: simple", description: "Parse xml: simple",
subdescription: "Notice how all the values are strings, see the next example on how you can fix that.", subdescription: "Notice how all the values are strings, see the next example on how you can fix that.",
input: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cat>\n <says>meow</says>\n <legs>4</legs>\n <cute>true</cute>\n</cat>", input: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cat>\n <says>meow</says>\n <legs>4</legs>\n <cute>true</cute>\n</cat>",
expected: "cat:\n says: meow\n legs: \"4\"\n cute: \"true\"\n", expected: "+p_xml: version=\"1.0\" encoding=\"UTF-8\"\ncat:\n says: meow\n legs: \"4\"\n cute: \"true\"\n",
}, },
{ {
description: "Parse xml: number", description: "Parse xml: number",
subdescription: "All values are assumed to be strings when parsing XML, but you can use the `from_yaml` operator on all the strings values to autoparse into the correct type.", subdescription: "All values are assumed to be strings when parsing XML, but you can use the `from_yaml` operator on all the strings values to autoparse into the correct type.",
input: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cat>\n <says>meow</says>\n <legs>4</legs>\n <cute>true</cute>\n</cat>", input: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cat>\n <says>meow</says>\n <legs>4</legs>\n <cute>true</cute>\n</cat>",
expression: " (.. | select(tag == \"!!str\")) |= from_yaml", expression: " (.. | select(tag == \"!!str\")) |= from_yaml",
expected: "cat:\n says: meow\n legs: 4\n cute: true\n", expected: "+p_xml: version=\"1.0\" encoding=\"UTF-8\"\ncat:\n says: meow\n legs: 4\n cute: true\n",
}, },
{ {
description: "Parse xml: array", description: "Parse xml: array",
subdescription: "Consecutive nodes with identical xml names are assumed to be arrays.", subdescription: "Consecutive nodes with identical xml names are assumed to be arrays.",
input: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<animal>cat</animal>\n<animal>goat</animal>", input: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<animal>cat</animal>\n<animal>goat</animal>",
expected: "animal:\n - cat\n - goat\n", expected: "+p_xml: version=\"1.0\" encoding=\"UTF-8\"\nanimal:\n - cat\n - goat\n",
}, },
{ {
description: "Parse xml: attributes", description: "Parse xml: attributes",
subdescription: "Attributes are converted to fields, with the default attribute prefix '+'. Use '--xml-attribute-prefix` to set your own.", subdescription: "Attributes are converted to fields, with the default attribute prefix '+'. Use '--xml-attribute-prefix` to set your own.",
input: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cat legs=\"4\">\n <legs>7</legs>\n</cat>", input: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cat legs=\"4\">\n <legs>7</legs>\n</cat>",
expected: "cat:\n +legs: \"4\"\n legs: \"7\"\n", expected: "+p_xml: version=\"1.0\" encoding=\"UTF-8\"\ncat:\n +legs: \"4\"\n legs: \"7\"\n",
}, },
{ {
description: "Parse xml: attributes with content", description: "Parse xml: attributes with content",
subdescription: "Content is added as a field, using the default content name of `+content`. Use `--xml-content-name` to set your own.", subdescription: "Content is added as a field, using the default content name of `+content`. Use `--xml-content-name` to set your own.",
input: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cat legs=\"4\">meow</cat>", input: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<cat legs=\"4\">meow</cat>",
expected: "cat:\n +content: meow\n +legs: \"4\"\n", expected: "+p_xml: version=\"1.0\" encoding=\"UTF-8\"\ncat:\n +content: meow\n +legs: \"4\"\n",
}, },
{ {
description: "Parse xml: custom dtd", description: "Parse xml: custom dtd",
@ -362,21 +363,21 @@ var xmlScenarios = []formatScenario{
{ {
description: "Encode xml: attributes", description: "Encode xml: attributes",
subdescription: "Fields with the matching xml-attribute-prefix are assumed to be attributes.", subdescription: "Fields with the matching xml-attribute-prefix are assumed to be attributes.",
input: "cat:\n +@name: tiger\n meows: true\n", input: "cat:\n +name: tiger\n meows: true\n",
expected: "<cat name=\"tiger\">\n <meows>true</meows>\n</cat>\n", expected: "<cat name=\"tiger\">\n <meows>true</meows>\n</cat>\n",
scenarioType: "encode", scenarioType: "encode",
}, },
{ {
description: "double prefix", description: "double prefix",
skipDoc: true, skipDoc: true,
input: "cat:\n +@+@name: tiger\n meows: true\n", input: "cat:\n ++@name: tiger\n meows: true\n",
expected: "<cat +@name=\"tiger\">\n <meows>true</meows>\n</cat>\n", expected: "<cat +@name=\"tiger\">\n <meows>true</meows>\n</cat>\n",
scenarioType: "encode", scenarioType: "encode",
}, },
{ {
description: "Encode xml: attributes with content", description: "Encode xml: attributes with content",
subdescription: "Fields with the matching xml-content-name is assumed to be content.", subdescription: "Fields with the matching xml-content-name is assumed to be content.",
input: "cat:\n +@name: tiger\n +content: cool\n", input: "cat:\n +name: tiger\n +content: cool\n",
expected: "<cat name=\"tiger\">cool</cat>\n", expected: "<cat name=\"tiger\">cool</cat>\n",
scenarioType: "encode", scenarioType: "encode",
}, },