I try to create a shell script that searches in an XML file for an attribute and create an element with the given attribute if this doesn't exist or delete the element if the attribute exists.
Here is the XML File:
<configuration name="distributor.conf" description="Distributor Configuration">
<lists>
<list name="CRproductionLoadshare">
<node name="fs100" weight="2"/>
<node name="fs101" weight="2"/>
</list>
<list name="AnyOtherGroup">
<node name="fs100" weight="2"/>
</list>
</lists>
</configuration>
And this is my Shellscript so far:
fs_name=fs
cnt=102
xmlstarlet ed \
--var fs "'$fs_name$cnt'" \
-a '//list' -t elem -n node -v "$fs_name$cnt" \
-i '//node' -t attr -n name -v "$fs_name$cnt" \
-i '//node' -t attr -n weight -v 2 \
-d '//node[.=$fs]/text()' <distributor.conf.xml
The expected Output is
<configuration name="distributor.conf" description="Distributor Configuration">
<lists>
<list name="CRproductionLoadshare">
<node name="fs100" weight="2"/>
<node name="fs101" weight="2"/>
<node name="fs102" weight="2"/>
</list>
<list name="AnyOtherGroup">
<node name="fs100" weight="2"/>
</list>
</lists>
</configuration>
But my script work like this:
<?xml version="1.0"?>
<configuration name="distributor.conf" description="Distributor Configuration">
<lists>
<list name="CRproductionLoadshare">
<node name="fs100" weight="2" name="fs102" weight="2"/>
<node name="fs101" weight="2" name="fs102" weight="2"/>
</list>
<list name="AnyOtherGroup">
<node name="fs100" weight="2" name="fs102" weight="2"/>
</list>
<node name="fs102" weight="2"/>
</lists>
</configuration>
How to change the shell script to reach the goal. At first, I want to add the node name="fs102" in case of that this node didn't exist.
The output:
Scheme:
node_exists
is assigned with boolean value indicating the needed node existence[ "$node_exists" = "false" ] && xmlstarlet ed ...
- the 2ndxmlstarlet
edit command will be only executed if thenode_exists
is not equal tofalse
The most difficult task at hand here is to build the XPath that selects the correct node.
Step 1: find the XPath you need
example 1: Select the node named
list
who has an attribute@name="CRproductionLoadshare"
and has a child namednode
with attribute@name="fs100"
.So you can search for the parent of that particular node named
node
.or a bit easier :
example 2: Select the node named
list
who has an attribute@name="CRproductionLoadshare"
and does not have a child namednode
with attribute@name="fs102"
.Here we can use the XPath
not
-functionStep 2: edit your XML-file with the XPath you just found
A: Just add the node if it is not there
So, since you now know the correct XPath to select the node, you can edit the XML-file accordingly by first inserting a subnode
-s
and then updating its values and attributes with-i
which outputs
B: Toggle the node
Toggling can be done by adding a fake attribute and then remove the node with that attribute:
The shell script that works for toggle the node looks like this:
Each time I run that script the inputfile toggle the node (add/delete) only in the list element with name CRproductionLoadshare.