Search code examples
xmlxq

How to parse XML into JSON with xq and output specific elements as numbers? (instead of strings)


I'm not too well versed when it comes down to xq/jq... I've been trying to parse something like this:

<?xml version="1.0"?>
<groups>
  <a>
    <count>1</count>
    <max>46</max>
    <name>foo</name>
  </a>
  <a>
    <count>3</count>
    <max>81</max>
    <name>bar</name>
  </a>
</groups>

into this: (note the lack of double quotes around the numbers)

[
  {
    "count": 1,
    "max": 46,
    "name": "foo"
  },
  {
    "count": 3,
    "max": 81,
    "name": "bar"
  }
]

I understand that a priori xq has no way to discard what is a number and what is a string. So I tried a few jq artifacts using 'select' among others but I couldn't make it work... so for now I'm bound to remove the double quotes with 'sed'... which I find very inelegant knowing that xq could easily do it.

Would anybody know the parameters to pass to xq in order to look for specific elements (i.e. 'count' & 'max') and apply a transformation (i.e. 'tonumber') only to those elements while leaving the rest of the elements untoched?

Thanks a lot in advance!


Solution

  • Since xq bundled along with kislyuk/yq uses jq underneath for DSL, you can use the tonumber function to convert the .count to their numeric equivalent

    xq '.groups.a | map( (.count, .max) |= tonumber )' xml
    [
      {
        "count": 1,
        "max": 46,
        "name": "foo"
      },
      {
        "count": 3,
        "max": 81,
        "name": "bar"
      }
    ]