create XML file using bash script

38,301

Solution 1

Print the line on this way:

echo '<root><foo a="b">'"$lorem"'</foo><bar value="ipsum" /></root>' >> "$MY_XML"

This is need because single quotes deny shell interpreter from replace environment variables inside

Solution 2

Use in-line document with cat

cat >destfile <<EOF
<your ZML here...where $vas expand happly>
but the rest remain as is
EOF

I used it in a lot of scripts. Consider also envsubst command to restrict variables you can use in the in-line document.

Solution 3

Frustratingly perhaps, one of the combinations you omitted would have worked:

echo "<root><foo a=\"b\">$lorem</foo><bar value=\"ipsum\" /></root>" >> $MY_XML

Single quotes leave everything exactly as you type it. Escaping with \ will not work. Double quotes will evaluate the string. Inside double quotes you can use \ to escape specific characters (including the double-quote character itself).

You could also combine parts of the string that are quoted in different ways. Here, $lorem remains double-quoted but the rest of the string is surrounded with single quotes:

echo '<root><foo a="b">'"$lorem"'</foo><bar value="ipsum" /></root>' >> $MY_XML

Solution 4

The issue is that you are using your variable in a single-quoted string. The shell will never expand variables in single quoted strings.

Another issue is that the value in $lorem would not be properly XML encoded, so that a value like <!-- would mess up the XML document and make it unparseable.

Instead, use the jo from https://jpmens.net/2016/03/05/a-shell-command-to-create-json-jo/ to create a JSON document and the yq tool from https://kislyuk.github.io/yq/ to convert this to XML:

% lorem=LOL
% jo -p root="$( jo 'foo[@a]'=b 'foo[#text]'="$lorem" 'bar[@value]'=ipsum )"
{
   "root": {
      "foo": {
         "@a": "b",
         "#text": "LOL"
      },
      "bar": {
         "@value": "ipsum"
      }
   }
}

Then pass this through yq -x to convert to XML. Keys starting with @ will be turned into node attributes, and the value of the #text key will be turned into the node's value.

% jo -p root="$( jo 'foo[@a]'=b 'foo[#text]'="$lorem" 'bar[@value]'=ipsum )" | yq -x
<root>
  <foo a="b">LOL</foo>
  <bar value="ipsum"></bar>
</root>

With the value <!-- in $lorem:

% lorem='<!--'
% jo -p root="$( jo 'foo[@a]'=b 'foo[#text]'="$lorem" 'bar[@value]'=ipsum )" | yq -x
<root>
  <foo a="b">&lt;!--</foo>
  <bar value="ipsum"></bar>
</root>
Share:
38,301

Related videos on Youtube

maihabunash
Author by

maihabunash

I am 17 years old and love to develop

Updated on September 18, 2022

Comments

  • maihabunash
    maihabunash over 1 year

    I want create simple xml file using bash script ( not with dom )

    but when I set value in the line then echo print the $lorem word and not the val

    lorem=LOL

    echo '<root><foo a="b">$lorem</foo><bar value="ipsum" /></root>' >> $MY_XML
    

    I also try this

    echo '<root><foo a="b">\$lorem</foo><bar value="ipsum" /></root>' >> $MY_XML
    
    echo '<root><foo a="b">"$lorem"</foo><bar value="ipsum" /></root>' >> $MY_XML
    
    echo '<root><foo a="b">\"$lorem\"</foo><bar value="ipsum" /></root>' >> $MY_XML
    

    but all these print the exactly the line and not the val

    please advice how to print the val $lorem ? as the following example

     <root><foo a="b">LOL</foo><bar value="ipsum" /></root>