Reputation: 196
Following from this questions, I am now able to update a specific variable in a number of XMLs.
However, they all have a lot (unnecessary) whitespaces and xmllint removes them all. I now have 50 lines modified and that makes it very hard to see the functional difference when looking at git diff. Is there a way for xmllint not to do that and only change the value I'm interested in? (I tried to take a look at xmllint's man but didn't find any option that seemed to that)
Example: Original file:
<target_tags>
<target_tag name="my_tag1" default="old_value1" />
<target_tag name="my_tag2" default="old_value2" />
<target_tag name="my_tag3" default="old_value3" />
</target_tags>
xmllint command:
xmllint --shell /tmp/tmp.xml << EOF
> cd //target_tag[@name="my_tag1"]/@default
> set new_value
> save
> bye
> EOF
/ > default > default > default >
Modified file:
<target_tags>
<target_tag name="my_tag1" default="new_value"/>
<target_tag name="my_tag2" default="old_value2"/>
<target_tag name="my_tag3" default="old_value3"/>
</target_tags>
Upvotes: 0
Views: 82
Reputation: 12662
A possible solution using xmllint
could be to output lines as is until the desired value is found. Then generate a simple xml doc with the line to modify preserving indentation
needle='name="my_tag1"'
new_value="new_value1"
while IFS=$'\n' read line; do
if ! grep -q "$needle" <<<"$line";then
# target line not found
echo "$line"
else
temp_file=$(mktemp)
# save fake xml doc to a temp file
echo -e "<root>\n$line\n</root>" > $temp_file
# Change the attribute
printf "%s\n" "cd //target_tag[@$needle]/@default" "set $new_value" 'save' 'bye' | xmllint --shell $temp_file >/dev/null
sed -n '3 p' $temp_file
rm $temp_file
fi
done < tmp.xml
Only the modified line will be changed
<target_tags>
<target_tag name="my_tag1" default="new_value"/>
<target_tag name="my_tag2" default="old_value2" />
<target_tag name="my_tag3" default="old_value3" />
</target_tags>
Upvotes: 0