Replace xml values -- Shell --

Hello all,

I try to create a bash script but till now without any positiv results.
The script should replace different variables in a text file with the right xml values

Look at the following xml file:

file.xml

===================================
<?xml version="1.0" encoding="UTF-8"?>
<Daten>
<export_date>2008-07-15 16:29:01</export_date>
<language>english</language>

temp.txt

===================================
All dates were exported at <export_date>
The text was translated in <language>

script.sh

===================================
#!/bin/bash

IFS=$'\n'

for i in `cat file.xml | sed 's/>/ /g' | awk '{print $1}' | sed 's/</ /g' | sed 's/ //g'`
do

	for j in \`grep "$i" temp.txt | sed 's/.*&lt;//g'|  sed 's/&gt;.*//g' \`
	do
		\#echo $j

for h in `cat temp.txt | sed -e "s/"$j"/$(cat file.xml | grep "$j" | sed 's/>/ /g' | sed 's/</ /g' | awk '{print $2}')/g" >> temp2 `
do
echo $h
done
done

done

The aim should be

All dates were exported at 2008-07-15 16:29:01
The text was translated in english.

Do you know how I could work on this?

thx

Hi,

first save the desired information in two variables using process substitution:

read date lang < <(sed -n "s#.*date>\(.*\)</.*#\1#p;s#.*age>\(.*\)</lan.*#\1#p" file.xml)

Then substitute the markers in the temp file:

sed "s/<export_date>/${date}/;s/<language>/${lang}/" temp.txt

HTH Chris

Sorry,

little typo. It must be:

{read date; read lang} < <(sed -n "s#.*date>\(.*\)</.*#\1#p;s#.*age>\(.*\)</lan.*#\1#p" test)

And if that doesn't work (it did on zsh but not on bash):

set -- $(sed -n "s#.*date>\(.*\)</.*#\1#p;s#.*age>\(.*\)</lan.*#\1#p" file.xml )

sed "s/<export_date>/${1} ${2}/;s/<language>/${3}/" temp.txt

Thanks a lot.
That has been helpful to me!

My last issue is that the original xml file included 420 lines.
Therefore if I create now all the variables manual and in the future will be change one line in the xml file or temp.txt, then I'm lost.
Have you any idee how can I use a simply way?

THX

ah, i see, try:

while IFS="><" read a id val b 
do 
  sed -n "s#<${id}>#${val}#p" temp.txt
done < file.xml >> output

This will print the substitutions to a file called output.

super recognition,

but if the temp.txt include some others line without variables "exp. just a text line" will be not forwarded to the output. Or some variables in xml file is empty will be also dropped.

I don't understand what you mean by your second point "Or some variables
in xml file is empty will be also dropped." The first problem should be solved.
But if you have two files with arbitrary data in them, you will have to use
more powerful tools like awk or perl and provide some more lines of examples of input and desired output.

while IFS=">" read a id val 
do 
    if [[ "$id" =~ "</" ]] then 
        VAL=${id%<*}; ID=${id#*</}
        sed "s/<${ID}>/${VAL}/" temp.txt >> temp
        mv temp temp.txt
    fi
done < file.xml

With the second point I mean if not values are setting exp. <test></test>.
You are right, with perl or awk is more easy to finish this task but unfortunately I don't have any experience in awk or perl.

Whatever the stdout now is:

Syntax error: "fi" unexpected (expecting "then")

Try to think a little bit. There will be no stdout as the output is
redirected to file called temp and under bash you have to put
the "then" on a new line.

while IFS=">" read a id val 
do 
    if [[ "$id" =~ "</" ]] 
    then 
        VAL=${id%<*}; ID=${id#*</}
        sed "s/<${ID}>/${VAL}/" temp.txt >> temp
        mv temp temp.txt
    fi
done < file.xml

�Try to think a little bit. � it's difficult to think at 3'o clock in the morning.
The script works, there is only one mistake left. If the variable of the xml file contains a slash, for example <Name>I/you/he/she/</Name> than the sed doesn't work.

My suggestion would be:

VAL1=$(echo "$id" | sed 's/\//\\\//g' | sed 's/</ </g' | awk '{print $1}')

sed "s/<${ID}>/${VAL1}/" temp.txt >> temp

Unfortunately other xml records will be ignored after the first column.
Exp. <Firstname>Jan Janus</Firstname>
In this example only the record Jan is recognized.

This is the new xml-file with your previously unmentioned special cases:

<?xml version="1.0" encoding="UTF-8"?>
<Daten>
<export_date>2008-07-15 16:29:01</export_date>
<language>english</language>
<Name>I/you/he/she/</Name> 
<Firstname>Jan Janus</Firstname>

This is the code:

while IFS=">" read a id val 
do 
    if [[ "$id" =~ "</" ]] 
    then 
        VAL=${id%<*}; ID=${id#*</}
        sed "s|<${ID}>|${VAL}|" temp.txt >> temp
        mv temp temp.txt
    fi
done < file.xml

This is my output:

All dates were exported at 2008-07-15 16:29:01
The text was translated in english
And his name is I/you/he/she/
And his other name ist Jan 

Notice, everything you had to change was replace the
"/" with "|" in the above sed statement.

For me the above code works flawlessly under zsh and bash.

Or with escaped slashes:

#!/bin/bash

while IFS=">" read a id val 
do 
    if [[ "$id" =~ "</" ]] 
    then 
        VAL=${id%<*}; ID=${id#*</}
        VAL=${VAL//\//\\\/};ID=${ID//\//\\\/};
        sed "s/<${ID}>/${VAL}/" ~/temp.txt >> ~/temp
        mv ~/temp ~/temp.txt
    fi
done < ~/file.xml

In the above output example the Janus after Jan is missing
(the script works but not my mouse).

But if there are still more special cases i would throw the script
away and start from scratch with perl or awk.

Christoph, thank you so much for your help.
I really appreciate it.

thx

-- thx --