Wednesday, November 30, 2011

Another approach to modfiy structured files (like config or XML files)

Vienna (Wien) - Hofburg - Labors of Hercules (Encounter with Antaeus - Garden of the Hesperides and Killing Augeas - Augean Stables)

Have you ever wondered if there is a more convenient way to modify xml documents, beside libxml2? Sure, there is the nice dom within Firefox, but outside of that?
Well, there is augeas. AFAIK initially a project to standardize the interface to modify configuration files, in other words a common syntax for different formats.
Files are parsed trough so called lenses. Those lenses transform the actual file (e.g. httpd.conf or passwd) into a tree, which than can be modified by a set of augeas commands.
As lenses are bi-directional the same lense can be used to read a file, and to dump the (internal augeas) tree back into a valid configuration file. A nice concept, ey?

A back to the topic, one of the lenses - Xml.lns - can be used to modify XML files.
The following example creates a dummy xml file and modifies it using augtool.

$ sudo yum install augeas tidyp

$ cat > abc.xml <<EOF
<world poo="bar">
<child>Hi there.</child>

$ augtool -LA -e <<EOF
# Load XML lense
set /augeas/load/xml/lens "Xml.lns"
set /augeas/load/xml/incl "$PWD/abc.xml"

# Dump internal tree
print /files

# Add a note
set /files/$PWD/abc.xml/world/note/#attribute/timestamp "now"
set /files/$PWD/abc.xml/world/note/#text "Wtf"

# Change the text of a node.
set /files/$PWD/abc.xml/world/child/#text "Hello World."

# Insert a new child after the present child
ins child after /files/$PWD/abc.xml/world/child
set /files/$PWD/abc.xml/world/child[2]/#text "Hello Mars."

# Insert a new child - anywhere ..
set /files/$PWD/abc.xml/world/child[3]/#text "Hello Jupiter Jones."

# More children
set /files/$PWD/abc.xml/world/child[4]/child/child/#text "Hello Mars."

print /files/$PWD/abc.xml

print /augeas//error

$ tidyp -xml -i -q < abc.xml

$ unlink abc.xml

With the help from the people at #augeas on freenode, I found out that (a) there is a small bug preventing the usage of relative paths and (b) You need a little knowledge about the format you are writin to. In the (xml) example above, you need to specify attributes before specifying a #text node, because they are written first. If they were specified the other way round, augeas would fail while saving.

No comments:

Post a Comment