Search code examples
xmlshellsedxml-parsingxmlstarlet

need to be able to add strings (paths) to an XML file using shell script


I need to be able to add strings (paths) to an XML file using shell script, This is the XML that I have:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<configurations>
    <smtpHost>smtp3.gmail.com</smtpHost>
    <smtpPort>25</smtpPort>
    <emailFrom>GitPushNotifier@gmail.com</emailFrom>
    <emailSubject>Push notification</emailSubject>
    <!-- Stash general URL-->
    <gitViewerURL>http://server0005.gmail.net:7990/projects/</gitViewerURL>
    <rule>
        <name>test_12.55.4</name>
        <repo>test</repo>
        <branch>refs/heads/12.55.4</branch>
        <emailTo>test@gmail.com</emailTo>
        <path>Server/.*/resources/schema/v.*/.*/.*-dbSchemaDescriptor\.xml,Server/.*/resources/SpringIOC/dataupgrader/v.*/.*/.*-dataUpgrader\.xml,Server/.*/java/com/hp/test/dataupgrader/v.*/.*/.*\.java,Server/.*/resources/indexes/v.*/.*\.index,Server/.*/resources/SpringIOC/vanilla/.*\.xml</path>
    </rule>
    <rule>
        <name>test_12.55.10</name>
        <repo>test</repo>
        <branch>refs/heads/12.55.10</branch>
        <emailTo>test@gmail.com</emailTo>
        <path>Server/.*/resources/schema/v.*/.*/.*-dbSchemaDescriptor\.xml,Server/.*/resources/SpringIOC/dataupgrader/v.*/.*/.*-dataUpgrader\.xml,Server/.*/java/com/hp/test/dataupgrader/v.*/.*/.*\.java,Server/.*/resources/indexes/v.*/.*\.index,Server/.*/resources/SpringIOC/vanilla/.*\.xml</path>
    </rule>
    <rule>
        <name>test_12.55.6</name>
        <repo>test</repo>
        <branch>refs/heads/12.55.6</branch>
        <emailTo>test@gmail.com</emailTo>
        <path>Server/.*/resources/schema/v.*/.*/.*-dbSchemaDescriptor\.xml,Server/.*/resources/SpringIOC/dataupgrader/v.*/.*/.*-dataUpgrader\.xml,Server/.*/java/com/hp/test/dataupgrader/v.*/.*/.*\.java,Server/.*/resources/indexes/v.*/.*\.index,Server/.*/resources/SpringIOC/vanilla/.*\.xml</path>
    </rule>
</configurations>

And I need to add additional path to the subnode only for one version (let's say for test_12.55.10), The path's I want to add are:

Server/./resources/schema/v12_55_10/./.-dbSchemaDescriptor.xml, Server/./resources/SpringIOC/dataupgrader/v12_55_10/./.-dataUpgrader.xml, Server/./java/com/hp/mqm/dataupgrader/v12_55_10/./..java, Server/./resources/indexes/v12_55_10/.*.index

I want to use sed or "xmlstarlet" as I saw other people suggested, So the output that I want to get is:

<path>Server/.*/resources/schema/v.*/.*/.*-dbSchemaDescriptor\.xml,Server/.*/resources/SpringIOC/dataupgrader/v.*/.*/.*-dataUpgrader\.xml,Server/.*/java/com/hp/test/dataupgrader/v.*/.*/.*\.java,Server/.*/resources/indexes/v.*/.*\.index,Server/.*/resources/SpringIOC/vanilla/.*\.xml,Server/.*/resources/schema/v12_55_10/.*/.*-dbSchemaDescriptor\.xml,
Server/.*/resources/SpringIOC/dataupgrader/v12_55_10/.*/.*-dataUpgrader\.xml,
Server/.*/java/com/hp/mqm/dataupgrader/v12_55_10/.*/.*\.java,
Server/.*/resources/indexes/v12_55_10/.*\.index</path>

Solution

  • It can be done with sed. Here is a small sed script that should work as long as path follows name in a rule:

    script.sed

    # filter for block from name to end of rule with the version:
    /<name>test_12.55.10<\/name>/,/<\/rule>/ {
        /<\/path>/ {
                    # this is a multiline second argument to s:
                    s+<\/path>+,\
                        Server/./resources/schema/v12_55_10/./.-dbSchemaDescriptor.xml,\
                        Server/./resources/SpringIOC/dataupgrader/v12_55_10/./.-dataUpgrader.xml,\
                        Server/./java/com/hp/mqm/dataupgrader/v12_55_10/./..java,\
                        Server/./resources/indexes/v12_55_10/.*.index\
                    </path>\
                    +;
                    # remove the whitespaces inserted above for readability
                    s/,[ \n]+Server//g;
                    }
        };
    

    You use it like this: sed -rf script.sed yourfile.xml.

    You might be able to fill the version number and additional paths from a shell script (note the additional backslashes after each Server line).