Как заставить XMLLINT поместить результаты --xpath в массив
Я хотел бы, чтобы выходные данные XMLLINT помещались в массив BASH. Но все, что я могу получить, это одна строка. Результаты будут возвращать много совпадений, причем ни один из них не будет содержать шаблон, который может помочь разобрать возвращенную строку.
- Я попытался --format и перенаправить ">" в текстовый файл.
- Я пробовал xpath все экземпляры
//
и только один/
mcv.xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<instance>
<absolutePath>/abc/def</absolutePath>
</instance>
<instance>
<absolutePath>/abc/hij</absolutePath>
</instance>
</root>
mcv.sh
#!/usr/bin/bash
declare -a wwArray=()
wwCount=$(xmllint --xpath 'count(//absolutePath)' "mcv.xml")
printf "wwCount: '%s' \n" ${wwCount}
i=1
while [ $i -le ${wwCount} ];
do
wwExtracted=$(xmllint --xpath '//absolutePath['${i}']/text ()' "mcv.xml")
printf " - absolutePath: '%s' \n" ${wwExtracted}
printf " - index: '%d' \n" ${i}
let i=i+1
done
Запустив это, вывод:
wwCount: '2'
- absolutePath: '/abc/def/abc/hij'
- index: '1'
XPath set is empty
- absolutePath: ''
- index: '2'
... тогда как я ожидаю, что вместо этого будет:
wwCount: '2'
- absolutePath: '/abc/def'
- index: '1'
- absolutePath: '/abc/hij'
- index: '2'
1 ответ
Наименьшее изменение, необходимое для того, чтобы ваш существующий код заработал, - это добавлять символы перед [$i]
, вот так:
#!/usr/bin/bash
wwCount=$(xmllint --xpath 'count(//absolutePath)' "mcv.xml")
for ((i=1; i<=wwCount; i++)); do
wwExtracted=$(xmllint --xpath '(//absolutePath)['"$i"']/text()' "mcv.xml")
printf " - absolutePath: '%s' \n" "$wwExtracted"
printf " - index: '%d' \n" "$i"
done
Тем не менее, это действительно неэффективно (запуск вашего XPath снова и снова). Рассмотреть возможность перехода от xmllint
вместо этого использовать XMLStarlet, который может быть инструктирован для вставки новых строк между выходными элементами, так что вы можете сказать bash загрузить эти элементы непосредственно в реальный массив оболочки:
#!/usr/bin/bash
readarray -t items < <(xmlstarlet sel -t -m '//absolutePath' -v './text()' -n <mcv.xml)
printf ' - absolutePath: %s\n' "${items[@]}"
Как только вы получили содержимое в массив (как создано readarray
выше), вы также можете выполнить итерацию по индексу:
for idx in "${!items[@]}"; do
printf ' - absolutePath: %s\n' "${items[$idx]}"
printf ' - index: %s\n' "$idx"
done