arraysxmlbash

bash script to write in specific part of xml file


My problem is that this code below puts the result from the beginning of the file but I want to put it in a specific place.

#!/bin/bash -x

USER_ID=( User1 User2 User3 )
USER_CONF=/opt/test/config.xml

for i in "${USER_ID[@]}"; do
      
     printf '<user><id>ID</id><name><%s/name></user>\n' "$i" >> "$USER_CONF"
 
done

What I get now in config.xml is:

<company="external">
    <enabled>true</enabled>
    <users="allowed">
        USER_TO_INSERT_HERE
    </users>
</company>


<user><id>ID</id><name><User1/name></user>
<user><id>ID</id><name><User2/name></user>
<user><id>ID</id><name><User3/name></user>

What I want to get after the script execution in config.xml is:

<company="external">
    <enabled>true</enabled>
    <users="allowed">
    <user><id>ID</id><name><User1/name></user>
    <user><id>ID</id><name><User2/name></user>
    <user><id>ID</id><name><User3/name></user>
    </users>
</company>

Do you know how can I record the values from the for and write them in a variable then to just sed that var in the code? I know how to sed it but don't know how to record in the var the values or something like that?


Solution

  • First of all, <users="allowed"> in an invalid XML-node. This should probably be something like <users permission="allowed">.

    Please use an XML parser like to edit your 'config.xml'.

    With "direct element constructors":

    $ xidel -s config.xml -e '
      x:replace-nodes(
        //users,
        <users permission="allowed">{
          for $user in ("User1","User2","User3") return
          <user><id>ID</id><name>{$user}</name></user>
        }</users>
      )
    ' --output-node-format=xml --output-node-indent
    

    With "computed constructors":

    $ xidel -s config.xml -e '
      x:replace-nodes(
        //users,
        function($x){
          element {$x/name()} {
            $x/@*,
            for $user in ("User1","User2","User3") return
            element user {
              element id {"ID"},
              element name {$user}
            }
          }
        }
      )
    ' --output-node-format=xml --output-node-indent
    

    Output:

    <company="external">
      <enabled>true</enabled>
      <users permission="allowed">
        <user>
          <id>ID</id>
          <name>User1</name>
        </user>
        <user>
          <id>ID</id>
          <name>User2</name>
        </user>
        <user>
          <id>ID</id>
          <name>User3</name>
        </user>
      </users>
    </company="external">
    

    Playground