I have the following base XML
<hibernate-configuration>
<session-factory>
<mapping />
</session-factory>
</hibernate-configuration>
That same base XML can contain some properties or not, for example:
<hibernate-configuration>
<session-factory>
<mapping />
<property name="driver_class">some-class</property>
<property name="driver_dialect">some-dialect</property>
</session-factory>
</hibernate-configuration>
Now i need to use xmlstarlet to insert those properties if they do not exist or update those values if they do exist without creating any duplicates. I know how to update and also know how to insert, but since i do not know in advance if those properties exist or not I have no idea how i can do that.
What would be the correct way of doing that ?
CodePudding user response:
Once you add property
, insert the name
attribute (separately):
xmlstarlet ed -s "/hibernate-configuration/session-factory" -t elem -name "property" -v "com.mysql.jdbc.Driver" -i "//property" -type attr -name "name" -v "driver_class" input.xml
CodePudding user response:
I don't see any "insert or update", or any xmlstarlet subcommands that are conditionals. Presumably you want to use xmlstarlet so you don't have to write XSLT.
This is the best I could come up with: the sel
subcommand returns a non-zero exit status if the xpath does not exist in the document.
#!/bin/bash
xpath_root="/hibernate-configuration/session-factory"
set_property() {
local file=$1 name=$2 value=$3
local xpath="$xpath_root/property[@name = '$name']"
local tmpfile=$(mktemp)
if xmlstarlet sel -t -v "$xpath" "$file" >/dev/null
then
# property exists, alter it
xmlstarlet ed -O -u "$xpath" -v "$value" "$file"
else
# property does not exists, add it
xmlstarlet ed -O \
-s "$xpath_root" -t elem -n "property" -v "$value" \
-a "$xpath_root/property[not(@name)]" -t attr -n "name" -v "$name" \
"$file"
fi > "$tmpfile" && mv "$tmpfile" "$file"
}
for file in base1.xml base2.xml; do
cp "$file" "$file.bak"
set_property "$file" driver_class "new class"
set_property "$file" driver_dialect "new dialect"
done
After running the script
$ diff base1.xml{.bak,}
3a4,5
> <property name="driver_class">new class</property>
> <property name="driver_dialect">new dialect</property>
and
$ diff base2.xml{.bak,}
4,5c4,5
< <property name="driver_class">some-class</property>
< <property name="driver_dialect">some-dialect</property>
---
> <property name="driver_class">new class</property>
> <property name="driver_dialect">new dialect</property>