xmlaugeas

Adding new nodes to XML file with Augeas


I have this XML file /opt/webapp/config.xml for a custom webapp that contains a parent node items.

<items>
</items>

I'm trying to add a list of new child nodes item with an attribute value while making sure the child node doesn't contain the end/closing tag because the app requires that format.

<items>
<item value="video/*"/><item value="audio/*"/><item value="application/rar"/><item value="application/x-zip"/><item value="application/x-gzip"/>
</items>

If I were to open up the existing configuration using augtool, I will get the below output.

/files/opt/webapp/config.xml/File/FileTypes
/files/opt/webapp/config.xml/File/FileTypes/#text = "\n"
/files/opt/webapp/config.xml/File/FileTypes/items
/files/opt/webapp/config.xml/File/FileTypes/items/#text = "\n"
/files/opt/webapp/config.xml/File/FileTypes/items/item[1] = "#empty"
/files/opt/webapp/config.xml/File/FileTypes/items/item[1]/#attribute
/files/opt/webapp/config.xml/File/FileTypes/items/item[1]/#attribute/value = "video/*"
/files/opt/webapp/config.xml/File/FileTypes/items/item[2] = "#empty"
/files/opt/webapp/config.xml/File/FileTypes/items/item[2]/#attribute
/files/opt/webapp/config.xml/File/FileTypes/items/item[2]/#attribute/value = "audio/*"
/files/opt/webapp/config.xml/File/FileTypes/items/item[3] = "#empty"
/files/opt/webapp/config.xml/File/FileTypes/items/item[3]/#attribute
/files/opt/webapp/config.xml/File/FileTypes/items/item[3]/#attribute/value = "application/rar"

I found a few posts here and here discussing about xml and Augeas but those examples follow the format with both starting and closing tag. For example: <item value="application/rar"></item>. And I'm trying to find a way to see if Augeas can also create and add child node with a self-closing tag only.

I'm using augtool (version 1.10.1) that comes with puppet agent 5.5.10 on RHEL 7.

Thank you.


Solution

  • As you can see in your example, self-closing tags have a value of #empty, so you just need to set that value on your items.

    So in your case, you could do something like:

    # set context to use relative paths later
    set /augeas/context /files/opt/webapp/config.xml/File/FileTypes/items
    
    # define a $video variable pointing to the video element, define it as self-closing
    defnode video item[#attribute/value="video/*"] "#empty"
    # Set element value
    set $video/#attribute/value "video/*"
    
    defnode audio item[#attribute/value="audio/*"] "#empty"
    set $audio/#attribute/value "audio/*"
    
    defnode rar item[#attribute/value="application/rar"] "#empty"
    set $rar/#attribute/value "application/rar"
    

    etc.

    resulting in:

    <items>
    <item value="video/*"/>
    <item value="audio/*"/>
    <item value="application/rar"/>
    </items>
    

    defnode will define a variable that points to a node and set its value if it doesn't exist yet. As a result, this code will be idempotent.