`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"
Просматривая документы , кажется, что нет способа обеспечить интерпретацию массива, когда есть один элемент.