`yq`, кажется, не может работать с XML только с одним элементом

Я использую следующую команду для извлечения данных из XML-файла:

      yq -p=xml '.resources.string[] | [.+@name, .+content] | join("|")' sample.xml

С входным XML-файлом, например:

      <resources>
    <string name="String-1">String 1</string>
    <string name="String-2">String 2</string>
</resource>

Команда отлично работает с выводом:

      String-1|String 1
String-2|String 2

Но если входной XML-файл содержит только один элемент:

      <resources>
    <string name="String-1">String 1</string>
</resource>

На выходе всего две пустые строки.

Входной файл читается правильно, и один элемент с одним атрибутом и одним содержимым правильно идентифицируется, но значения почему-то отбрасываются. Если не выполнять операцию соединения с одним и тем же входным XML-файлом с одним элементом:

      yq -p=xml '.resources.string[] | [.+@name, .+content] ' input.xml 

Результат:

      []
[]

Это похоже на ошибку, но возможно, я пропустил какие-то настройки. Любое обходное решение или исправление?

Я используюyqверсияv4.34.2установлен с помощью Brew на MacOS (Intel) 13.4.1

2 ответа

Как отметил @larsks, случай с одним элементом рассматривается как сам элемент, а не как массив, содержащий этот один элемент. Это (к сожалению) наиболее распространенный способ для различных инструментов-конвертеров интерпретировать и транскодировать XML в такие структуры, как YAML или JSON. И ниyqни от mikefarah/yq , ни от kislyuk/yq делают это поведение необязательным.

Однако вы можете включить переключатель в свой фильтр. Проверьте входные данныеtypeи выполнять итерацию только в том случае, если это массив:

      yq -p=xml '.resources.string | (select(type == "!!seq") | .[]) // . | [.+@name, .+content] | join("|")'

Сxq, вы можете сделать то же самое, но используяarrays ярлык (который разрешает выбор по типу), предоставленныйjqправильный:

      xq -r '.resources.string | arrays[] // . | [."@name", ."#text"] | join("|")'

Проблема здесь в том, что во втором примере лечитresources.stringкак словарь, а не как массив. Сравните выводyq -pxml .resourcesмежду первым примером:

      string:
  - +content: String 1
    +@name: String-1
  - +content: String 2
    +@name: String-2

И второй пример:

      string:
  +content: String 2
  +@name: String-2

Итак, для вашего второго примера вы можете запросить:

      $ yyq -pxml -oyml '.resources.string|[.+@name, .+content]|join("|")' < sample2.xml
String-2|String 2

Второй пример рассматривается как словарь, потому что именно такyqобрабатывает элемент с отдельными дочерними элементами, например:

      <cat>
  <says>meow</says>
  <legs>4</legs>
  <cute>true</cute>
</cat>

Что становится:

      cat:
  says: meow
  legs: "4"
  cute: "true"

Просматривая документы , кажется, что нет способа обеспечить интерпретацию массива, когда есть один элемент.

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