Fixed update children problem with xml

This commit is contained in:
Mike Farah 2023-10-05 16:29:12 +11:00
parent b2a3cb47a7
commit b0ff65d6b7
5 changed files with 17 additions and 16 deletions

View File

@ -1,3 +1,2 @@
{name: Mike} - cat
--- - dog
{name: Bob}

View File

@ -1 +1 @@
<cat>3</cat> <zoo><thing><frog>boing</frog></thing></zoo>

View File

@ -129,21 +129,20 @@ zoo:
``` ```
## Parse xml: force all as an array ## Parse xml: force all as an array
Because of the way yq works, when updating everything you need to update the children before the parents. By default `..` will match parents first, so we reverse that before updating.
Given a sample.xml file of: Given a sample.xml file of:
```xml ```xml
<zoo><thing><frog>boing</frog></thing></zoo> <zoo><thing><frog>boing</frog></thing></zoo>
``` ```
then then
```bash ```bash
yq -oy '([..] | reverse | .[]) |= [] + .' sample.xml yq -oy '.. |= [] + .' sample.xml
``` ```
will output will output
```yaml ```yaml
zoo: - zoo:
thing: - thing:
frog: boing - frog:
- boing
``` ```
## Parse xml: attributes ## Parse xml: attributes

View File

@ -45,7 +45,11 @@ func assignUpdateOperator(d *dataTreeNavigator, context Context, expressionNode
return context, err return context, err
} }
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() { //traverse backwards through the context -
// like delete, we need to run against the children first.
// (e.g. consider when running with expression '.. |= [.]' - we need
// to wrap the children first
for el := lhs.MatchingNodes.Back(); el != nil; el = el.Prev() {
candidate := el.Value.(*CandidateNode) candidate := el.Value.(*CandidateNode)
rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.RHS) rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.RHS)

View File

@ -364,11 +364,10 @@ var xmlScenarios = []formatScenario{
expected: "zoo:\n animal:\n - cat\n", expected: "zoo:\n animal:\n - cat\n",
}, },
{ {
description: "Parse xml: force all as an array", description: "Parse xml: force all as an array",
subdescription: "Because of the way yq works, when updating everything you need to update the children before the parents. By default `..` will match parents first, so we reverse that before updating.", input: "<zoo><thing><frog>boing</frog></thing></zoo>",
input: "<zoo><thing><frog>boing</frog></thing></zoo>", expression: ".. |= [] + .",
expression: "([..] | reverse | .[]) |= [] + .", expected: "- zoo:\n - thing:\n - frog:\n - boing\n",
expected: "- zoo:\n - thing:\n - frog:\n - boing\n",
}, },
{ {
description: "Parse xml: attributes", description: "Parse xml: attributes",