create XML file using bash script

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>
Asked By: maihabunash

||

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

Answered By: Romeo Ninov

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
Answered By: roaima

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.

Answered By: daitangio

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 a value like <!-- would mess up the XML document and make it unparseable.

Instead, use 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 'foo[@a]'=b 'foo[#text]'="$lorem" 'bar[@value]'=ipsum
{
   "foo": {
      "@a": "b",
      "#text": "LOL"
   },
   "bar": {
      "@value": "ipsum"
   }
}

Then pass this through yq -x --xml-root=root . to convert to XML and wrap it in a top-level root node called root. 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 'foo[@a]'=b 'foo[#text]'="$lorem" 'bar[@value]'=ipsum | yq -x --xml-root=root .
<root>
  <foo a="b">LOL</foo>
  <bar value="ipsum"></bar>
</root>

With the value <!-- in $lorem:

$ lorem='<!--'
$ jo 'foo[@a]'=b 'foo[#text]'="$lorem" 'bar[@value]'=ipsum | yq -x --xml-root=root .
<root>
  <foo a="b">&lt;!--</foo>
  <bar value="ipsum"></bar>
</root>

Or, with the literal value $lorem in the variable:

$ lorem='$lorem'
$ jo 'foo[@a]'=b 'foo[#text]'="$lorem" 'bar[@value]'=ipsum | yq -x --xml-root=root .
<root>
  <foo a="b">$lorem</foo>
  <bar value="ipsum"></bar>
</root>
Answered By: Kusalananda

When you interpolate values into XML template make sure to escape special characters:

escape() {
    local val
    val=$1
    val=${val//&/&amp;}
    val=${val//</&lt;}
    val=${val//>/&gt;}
    val=${val//'/&apos;}
    val=${val//"/&quot;}
    printf %s "$val"
}

lorem=""Foo" & 'Bar' & <Baz>"

cat << EOF
<root><foo a="b">$(escape "$lorem")</foo><bar value="ipsum" /></root>
EOF
Answered By: pmartycz
Categories: Answers Tags: , , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.