Changing the content of a configuration file on an Unix system, like Linux, can be easy. That task quickly becomes a whole different ballgame when you’re dealing with XML files, because this format imposes a couple of restrictions on the XML element values, for instance. You’ll probably be able to get the job done when using traditional tools like sed
and awk
, but I would advise against it.
First things first. I feel it’s best to use an XML editing tool to modify an XML file because of the constraints the XML format enforces. Everybody knows that certain characters, like < and &, must be encoded when used in an element value. There are more limits, but safeguarding against those in a sed
statement is just a lot of lost energy.
Now what’s the best way to script XML file changes on a Linux system then? I don’t know, but I can think of two options. The first would be XSLT, but that might prove to be too complex. The other is a specialized tool called xmlstarlet
and it works great. Changing XML files was easier that I had imagined.
Now if you’re updating an XML file using elements with a default XML namespace, xmlstarlet
will give you some trouble when using an XPath expression. It’s real easy to solve. Say the XML document looks like this:
<root xmlns="urn:bastb:root-example:2.0"> <sub1 xmlns="urn:bastb:sub-example:2.0"> <subsub1 name="attribute-value" /> </sub1> <sub2 host="localhost"> <for name="counter" start="1" max="99" step="1" /> </sub2> </root>
Setting the value of the max
attribute to 101
on for
and the updating the value of the name
attribute on subsub1
element can be archieved by this command line:
xmlstarlet ed -N mu=urn:bastb:root-example:2.0 -N bu=urn:bastb:sub-example:2.0 \ -u '/mu:root/mu:sub2[@host="localhost"]/mu:for[1]/@max' -v 101 \ -u '/mu:root/bu:sub1/bu:subsub1/@name' -v sometest
xmlstarlet
is an impressive piece of work. It allows you to add elements, with a bunch of attributes in a snap, like this post on stackoverflow illustrates. The tool allows you to modify existing attribute values, or even add an attribute. There’s an issue with xmlstarlet producing invalid XML when adding an existing attribute, but it’s not that hard to test for it.
Feedback is appreciated