0

I have an xml file which has several elements (3rd and 4th level <def> as well as <ex> and <kref> ) that may repeat 1 or more times. When I convert this to json (and evenually yaml with yq), the multiple elements are arrays and understandably the single elments are not. How can I make jq/yq consisently render an element in an array even as a single item.

For brevity, I have included below sample xml and json data with the single elements as well as the desired json output where the single elements would be rendered as an array.

I have also tried converting with cat test.xml | xq '.xdxf.lexicon.ar[].def.def.def=[.def]' , and this seems to be starting to get me somewhere, but the resulting def array is empty. Any help on solving this much appreciated.

original xml:

<xdxf revision="034">
  <lexicon>
    <ar>
      <k xml:lang="dyu">headword2</k>
      <def freq="">
        <co></co>
        <def xml:lang="fr">
          <def def-id="63491b7b-5d72-400c-95ee-f2e63f984832">
            <gr>
              <abbr></abbr>
            </gr>
            <co></co>
            <def def-id="32dc09fd-212f-42da-9f45-7d0fa5258c49">
              <deftext>
                <dtrn>definition1</dtrn>
              </deftext>
              <ex type="exm" ex-id="dda450aa-121b-415f-92e4-63366fd78fb5">
                <ex_orig></ex_orig>
                <ex_tran></ex_tran>
              </ex>
              <etm></etm>
              <categ></categ>
            </def>
          </def>
        </def>
        <sr>
          <kref type="spv"></kref>
        </sr>
      </def>
    </ar>
  </lexicon>
</xdxf>

piped to jq .

{
  "xdxf": {
    "@revision": "034",
    "lexicon": {
      "ar": {
        "k": {
          "@xml:lang": "dyu",
          "#text": "headword2"
        },
        "def": {
          "@freq": "",
          "co": null,
          "def": {
            "@xml:lang": "fr",
            "def": {
              "@def-id": "63491b7b-5d72-400c-95ee-f2e63f984832",
              "gr": {
                "abbr": null
              },
              "co": null,
              "def": {
                "@def-id": "32dc09fd-212f-42da-9f45-7d0fa5258c49",
                "deftext": {
                  "dtrn": "definition1"
                },
                "ex": {
                  "@type": "exm",
                  "@ex-id": "dda450aa-121b-415f-92e4-63366fd78fb5",
                  "ex_orig": null,
                  "ex_tran": null
                },
                "etm": null,
                "categ": null
              }
            }
          },
          "sr": {
            "kref": {
              "@type": "spv"
            }
          }
        }
      }
    }
  }
}

Desired output:

{
  "xdxf": {
    "@revision": "034",
    "lexicon": {
      "ar": {
        "k": {
          "@xml:lang": "dyu",
          "#text": "headword2"
        },
        "def": {
          "@freq": "",
          "co": null,
          "def": {
            "@xml:lang": "fr",
            "def": [
            {
              "@def-id": "63491b7b-5d72-400c-95ee-f2e63f984832",
              "gr": {
                "abbr": null
              },
              "co": null,
              "def": [ 
              {
                "@def-id": "32dc09fd-212f-42da-9f45-7d0fa5258c49",
                "deftext": {
                  "dtrn": "definition1"
                },
                "ex": [
                 {
                   "@type": "exm",
                   "@ex-id": "dda450aa-121b-415f-92e4-63366fd78fb5",
                   "ex_orig": null,
                   "ex_tran": null
                  }
                ],
                "etm": null,
                "categ": null
               }
              ]
             }
            ]
          },
          "sr": {
            "kref": [
              {
              "@type": "spv"
            }
            ]
          }
        }
      }
    }
  }
}
Boyd
  • 351
  • 4
  • 14
  • so you want every 3th and 4th `def` converted to an array with that object? – 0stone0 Jun 16 '22 at 20:57
  • Yes. Hopefully if I can see how that is done I can also see how to do convert ex and kref as well. – Boyd Jun 16 '22 at 21:57
  • Similar issue seems to be described here: https://stackoverflow.com/questions/44100383/handling-json-single-object-and-array Question is still can jq help out? – Boyd Jun 17 '22 at 13:32

1 Answers1

0

My comment:
So you want every 3'th and 4'th def converted to an array with that object?

OP's comment:
Yes. Hopefully if I can see how that is done I can also see how to do convert ex and kref as well.


.xdxf.lexicon.ar.def.def.def |= [ (.def |= [ . ]) ]
  1. First we select the 3'th def:
    .xdxf.lexicon.ar.def.def.def
  2. Then we use an update assignment to change it's value to an array, with the object inside
    Normally we'd use |= [ . ] to do that
  3. But since we need to perform the same action on the 4'th def, we apply the same logic inside the array to wrap the 4'th def:
    (.def |= [ . ])
    The () is used to ensure the |= only applies to that object.

Result JSON, visible in this online demo:

{
  "xdxf": {
    "@revision": "034",
    "lexicon": {
      "ar": {
        "k": {
          "@xml:lang": "dyu",
          "#text": "headword2"
        },
        "def": {
          "@freq": "",
          "co": null,
          "def": {
            "@xml:lang": "fr",
            "def": [
              {
                "@def-id": "63491b7b-5d72-400c-95ee-f2e63f984832",
                "gr": {
                  "abbr": null
                },
                "co": null,
                "def": [
                  {
                    "@def-id": "32dc09fd-212f-42da-9f45-7d0fa5258c49",
                    "deftext": {
                      "dtrn": "definition1"
                    },
                    "ex": {
                      "@type": "exm",
                      "@ex-id": "dda450aa-121b-415f-92e4-63366fd78fb5",
                      "ex_orig": null,
                      "ex_tran": null
                    },
                    "etm": null,
                    "categ": null
                  }
                ]
              }
            ]
          },
          "sr": {
            "kref": {
              "@type": "spv"
            }
          }
        }
      }
    }
  }
}
0stone0
  • 34,288
  • 4
  • 39
  • 64