Использование XMLStarlet, это будет выглядеть что-то вроде следующего:
#!/bin/bash
# usage: [script] [flatfile-name] <in.xml >out.xml
flatfile=$1
# store an array of variables, and an array of edit commands
xml_vars=()
xml_cmd=()
count=0
while read -r line; do
[[ $line = *"~"* ]] || continue
key=${line%%"~"*} # put everything before the ~ into key
key=${key//"."/"/"} # change "."s to "/"s in key
val=${line#*"~"} # put everything after the ~ into val
# assign key to an XMLStarlet variable to avoid practices that can lead to injection
xml_vars+=(--var "var$count" "'$key'")
# update the first value following a matching name
xml_cmd+=(-u "//name[.=\$var${count}]/following-sibling::value[1]" \
-v "$val")
# increment the counter used to assign variable names
((++count))
done <"$flatfile"
if ((${#xml_cmd[@]})); then
xmlstarlet ed "${xml_vars[@]}" "${xml_cmd[@]}"
else
cat # no edits to do
fi
Это будет запускать команду, как в следующем:
xmlstarlet ed \
--var var0 "Application/Env" \
--var var2 "Application/ID" \
--var var3 "Application/Name" \
-u '//name[.=$var0]/following-sibling::value[1]' -v 'DEV' \
-u '//name[.=$var1]/following-sibling::value[1]' -v '999' \
-u '//name[.=$var2]/following-sibling::value[1]' -v 'appname'
... который заменяет первое значение после того, как имя Application/Env
с DEV
, первое значение после имени Application/ID
с 999
и первое значение после названия Application/Name
с appname
.
Несколько менее параноидальный подход может вместо того, чтобы генерировать запросы, как //name[.="Application/Name"]/following-sibling::value[1]
; включение переменных вне диапазона выполняется в качестве практики обеспечения безопасности. Рассмотрим, что может произойти в противном случае, если содержащиеся в файле ввода:
Application.Foo"or 1=1 or .="~bar
... и в результате XPath были
//name[.="Application/Foo" or 1=1 or .=""]/following-sibling::value[1]
Поскольку 1=1
всегда верно, это будет тогда соответствовать каждый имя, и, таким образом, изменить каждые значение в файле bar
.
К сожалению, реализация XMLStarlet не защищает от этого; однако использование переменных связывания делает возможным для реализации, чтобы обеспечить такие меры предосторожности, поэтому будущий выпуск может быть безопасным в этом контексте.
Кстати, ваш «XML как это» на самом деле недостаточно хорош для проверки правильности. Заголовок имеет важное значение: если обрабатываемый XML-файл начинается с '', это означает что-то совершенно иное, чем если оно только начиналось с ''. –
ocbit: 'sed',' awk' и т. Д.не может справиться с XML надежно - синтаксис * совсем не * контекстно-свободный, то есть вам нужно отслеживать, какие атрибуты xmlns были замечены в предыдущих тегах, независимо от того, находитесь ли вы в комментарии, независимо от того, в разделе CDATA и т. д. решить, что делать в любой момент времени. (И это прежде чем иметь дело с вещами, такими как расширение сущностей, или значениями, которые нужно избегать, чтобы не нарушать синтаксис). См. Также соответствующий http://stackoverflow.com/a/1732454/14122 –