xmlaugeas

Adding new lines and tabs in XML using Augeas


This is related to my previous post for updating xml using Augeas. I manually adjusted the format and was able to look at how the new line and tabs were added and parsed in augtool. I tried to add those new lines but not being able to insert each #text line between the items node and child item nodes. Would it be possible to add new lines and tabs by setting a new variable for items/#text?

Is this something doable with Augeas to insert those characters?

        <FileTypes>
        <items>
        <item value="video/*"/>
        <item value="audio/*"/>
        <item value="application/rar"/>
        </items>
        </FileTypes>      
/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[1] = "\n\t\t"
/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/#text[2] = "\t\t"
/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/#text[3] = "\t\t"
/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 have something like this below to insert a new line but it didn't seem to be working and only added a literal new line and tab characters.

set /files/opt/webapp/config.xml/File/FileTypes/items/#text \n\t\t'

And that would result in even worse condition.

        <FileTypes>
        <items>\n\t\t<item value="video/*"/>
<item value="audio/*"/>
<item value="application/rar"/>
</items>
        </FileTypes>      

Solution

  • I've scratched my head a bit to come up with an elegant, idempotent solution to ensure your <item> nodes are indented by one tabulation. Here's a suggestion:

    # define $audio (see previous question)
    defnode audio item[#attribute/value="audio/*"] "#empty"
    
    # define $noindent as $audio if the immediate previous node is not a `#text` one
    defvar noindent $audio[preceding-sibling::*[1][label()!="#text"]]
    
    # insert a #text element before $noindent. Will fail silently if $noindent doesn't match anything, making the change idempotent
    ins #text before $noindent
    
    # Set the value of the next #text node, which we are sure exists now
    set #text[following-sibling::*[1][#attribute/value="audio/*"]] "\t"
    

    Generally speaking, #text works fine, and your problem was most likely a wrong quoting of the value.