1

I have an XML data in the following form:

<string name="app_name">my App</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="done">Done</string>

I'm trying to write a Bash script for converting the XML to something like this:

<string comment="for more see http://www.web.com/test/app_name" name="app_name">my App</string>
<string comment="for more see http://www.web.com/test/yes" name="yes">Yes</string>

I did some search and here's what I have found so far.

The code below is making a replacement is every element:

 sed -i 's/<string/<string comment=\"for more see http:\/\/www\.web\.com\/test\/\"    /g' string.xml

And this expression fetches the name attribute:

Sname=$(sed '/name/s/\(.*name=\)\(.*\)/\2/' string.xml|awk -F\" '{print $2}')

But I have no idea how to merge them.

1 Answer 1

3

It is unsafe to use sed, or awk for XML parsing. These tools are very flexible, but they have no built-in XML parsing features. It is very tedious and impractical to implement an XML parser in sed, or awk. I recommend using an XML parser such as xmlstarlet (which is actually more than a parser).

Example

xmlstarlet ed -a '//string[@name]' -t attr -n comment src.xml | \
  xmlstarlet ed -u '//string/@comment' \
  -x 'concat("see http://www.web.com/test/app_name/", ../@name)' > out.xml

The first xmlstarlet command parses src.xml file, appends an empty comment attribute to all string tags having name attribute (using '//string[@name]' XPath expression). The output of the command is passed to the second command through pipeline (|).

The second command reads XML from the pipeline, and updates the comment attributes with the concat() function which, in particular, concatenates the static string "see http://www.web.com/test/app_name/" with the value of name attribute (../@name stands for "name attribute of the parent node").

The output of the second command is redirected to out.xml file.

Sample Input

<root x="10">
  <string name="app_name">my App</string>
  <string name="yes">Yes</string>
  <string name="no">No</string>
  <string name="done">Done</string>
</root>

Sample Output

<?xml version="1.0"?>
<root x="10">
  <string name="app_name" comment="see http://www.web.com/test/app_name/app_name">my App</string>
  <string name="yes" comment="see http://www.web.com/test/app_name/yes">Yes</string>
  <string name="no" comment="see http://www.web.com/test/app_name/no">No</string>
  <string name="done" comment="see http://www.web.com/test/app_name/done">Done</string>
</root>
Sign up to request clarification or add additional context in comments.

2 Comments

hi, Thanks for perfect solution, I changed xml to xmlstarlet and it is working like charm. Can you explain how it works, parameters and explanation if possible for sake of learning
@user2299735, added some extra info. Please accept the answer, if you think it fixes your problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.