Search code examples
xmlbashxmlstarlet

Change xml attributes with xmlstarlet


Here is the content of my xml file

<?xml version="1.0" encoding="UTF-8"?>
<data-sources>
    <data-source id="mariaDB-162b8e6bd5d-176d08c17fde61cb" provider="mysql" driver="mariaDB" name="MariaDB - app" save-password="true" show-system-objects="true" read-only="false">
        <connection host="172.23.0.4" port="3306" server="" database="portal" url="jdbc:mysql://172.23.0.4:3306/portal" user="portal" password="fakepassword" home="/usr" type="dev">
            <network-handler type="TUNNEL" id="ssh_tunnel" enabled="false" save-password="false">
                <property name="sshConnectTimeout" value="10000"/>
                <property name="port" value="22"/>
                <property name="implementation" value="jsch"/>
                <property name="authType" value="PASSWORD"/>
            </network-handler>
            <network-handler type="PROXY" id="socks_proxy" enabled="false" save-password="false">
                <property name="socks-port" value="1080"/>
            </network-handler>
            <network-handler type="CONFIG" id="mysql_ssl" enabled="false" save-password="false">
                <property name="ssl.public.key.retrieve" value="false"/>
                <property name="ssl.verify.server" value="true"/>
                <property name="ssl.require" value="false"/>
            </network-handler>
        </connection>
    </data-source>
    <filters/>
</data-sources>

For example I want to be able to change

<connection host="172.23.0.4" port="3306" server="" database="portal" url="jdbc:mysql://172.23.0.4:3306/portal" user="portal" password="fakepassword" home="/usr" type="dev">

to

<connection host="172.28.0.8" port="3306" server="" database="portal" url="jdbc:mysql://172.28.0.8:3306/portal" user="portal" password="fakepassword" home="/usr" type="dev">

So i need to change the host property and the url dynamically. I tried:

xmlstarlet ed -u "/data-sources/data-source/connection[@host]/@host" -v '172.28.0.8' .dbeaver-data-sources.xml

but it doesn't work, the file doesn't change.


Solution

  • In addition to the --inplace advice, changing multiple attributes must be done with multiple invocations

    declare -A host=([old]=172.23.0.4 [new]=172.23.0.8) 
    new_url="jdbc:mysql://${host[new]}:3306/portal"
    
    xmlstarlet ed -u "//connection[@host = '${host[old]}']/@host" -v "${host[new]}" file.xml |
    xmlstarlet ed -u "//connection[@host = '${host[new]}']/@url"  -v "$new_url"
    
    <?xml version="1.0" encoding="UTF-8"?>
    <data-sources>
      <data-source id="mariaDB-162b8e6bd5d-176d08c17fde61cb" provider="mysql" driver="mariaDB" name="MariaDB - app" save-password="true" show-system-objects="true" read-only="false">
        <connection host="172.23.0.8" port="3306" server="" database="portal" url="jdbc:mysql://172.28.0.8:3306/portal" user="portal" password="fakepassword" home="/usr" type="dev">
          <network-handler type="TUNNEL" id="ssh_tunnel" enabled="false" save-password="false">
            <property name="sshConnectTimeout" value="10000"/>
            <property name="port" value="22"/>
            <property name="implementation" value="jsch"/>
            <property name="authType" value="PASSWORD"/>
          </network-handler>
          <network-handler type="PROXY" id="socks_proxy" enabled="false" save-password="false">
            <property name="socks-port" value="1080"/>
          </network-handler>
          <network-handler type="CONFIG" id="mysql_ssl" enabled="false" save-password="false">
            <property name="ssl.public.key.retrieve" value="false"/>
            <property name="ssl.verify.server" value="true"/>
            <property name="ssl.require" value="false"/>
          </network-handler>
        </connection>
      </data-source>
      <filters/>
    </data-sources>