Как преобразовать XML в JSON с помощью xq и вывести определенные элементы в виде чисел? (вместо строк)

Я не очень хорошо разбираюсь в xq/jq... Я пытался разобрать что-то вроде этого:

<?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>

в это: (обратите внимание на отсутствие двойных кавычек вокруг чисел)

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

Я понимаю, что априори xq не имеет возможности отбросить, что такое число, а что строка. Поэтому я попробовал несколько артефактов jq, используя 'select' среди других, но у меня не получилось заставить его работать... так что пока я обязан удалить двойные кавычки с помощью 'sed'... что я считаю очень неэлегантным, зная, что xq легко может это сделать.

Кто-нибудь знает, какие параметры нужно передать в xq, чтобы искать определенные элементы (например, "count" и "max") и применять преобразование (например, "tonumber") только к этим элементам, оставляя остальные элементы нетронутыми?

Заранее большое спасибо!

2 ответа

Решение

Поскольку xqв комплекте с kislyuk/yq использует jq внизу для DSL вы можете использовать tonumber функция для преобразования .count к их числовому эквиваленту

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

Общий подход к вашей задаче - рекурсивно перебрать все узлы и попытаться преобразовать их в числа.

xq 'walk(if type == "string" then tonumber? // . else . end)'

Если вы просто хотите обновить определенную часть ввода, вы можете сделать это:

xq '.groups.a |= walk(if type == "string" then tonumber? // . else . end)'

См. Также преобразование строк в числа в jq

Другие вопросы по тегам