xmlshellxml-parsing

Add xml element in a xml file using shell script


i have an xml file where i need to add data, i tried using sed. Could anyone help me out where i am doing wrong.

i have an xml file like this :

<!DOCTYPE sf-migration
PUBLIC "-//VA Software, Inc.//DTD SourceForge Migration 1.0//EN"
"/opt/add-ons/import-6.1/dtd/sf-migration_1_0.dtd">
<sf-migration toVersion="6.1.0.0" fromVersion="5.0.0.0">
<users></users>
</sf-migration>

Now i need to add the below file in users :

<sfuser xid="user1000">
           <username>beq03838</username>
           <email>noreply@nxp.com</email>
           <alternateEmail1></alternateEmail1>
           <dateCreated>2016-12-20 14:02:23 CET</dateCreated>
           <dateLastModified>2016-12-20 14:02:23 CET</dateLastModified>
           <detail></detail>
           <monitoringPreference>email</monitoringPreference>
           <lastLogin></lastLogin>
      </sfuser>

And my output should be the below :

enter <!DOCTYPE sf-migration
PUBLIC "-//VA Software, Inc.//DTD SourceForge Migration 1.0//EN"
"/opt/add-ons/import-6.1/dtd/sf-migration_1_0.dtd">
<sf-migration toVersion="6.1.0.0" fromVersion="5.0.0.0">
<users>
<sfuser xid="user1000">
<username>beq03838</username>
<email>noreply@nxp.com</email>
<alternateEmail1></alternateEmail1>
<dateCreated>2016-12-20 14:02:23 CET</dateCreated>
<dateLastModified>2016-12-20 14:02:23 CET</dateLastModified>
<lastLogin></lastLogin>
</sfuser>
</users>
</sf-migration>

I use the below shell script to append the text :

CONTENT=give the suer content
C=$(echo $CONTENT | sed 's/\//\\\//g')
sed "/<\/users>/ s/.*/${C}\n&/" /tmptest/user1.xml

What am i doing wrong ? is there any other simple way to add element in xml ? and i need this to be done in shell, as my complete code is in shell


Solution

  • Working with multiple files and escaping on the command line is super error-prone and hacky. You can achieve the same with a really small script in most languages. Here's an example in Python 2:

    template = open("user.xml").read()
    snippet = open("user_data.xml").read()
    result = template.replace("</users>", snippet + "</users>")
    open("user.xml", "w").write(result)
    

    Output:

    <!DOCTYPE sf-migration PUBLIC "-//VA Software, Inc.//DTD SourceForge Migration 1.0//EN" "/opt/add-ons/import-6.1/dtd/sf-migration_1_0.dtd"> <sf-migration toVersion="6.1.0.0" fromVersion="5.0.0.0">
    <users>
        <sfuser xid="user1000">
               <username>beq03838</username>
               <email>noreply@nxp.com</email>
               <alternateEmail1></alternateEmail1>
               <dateCreated>2016-12-20 14:02:23 CET</dateCreated>
               <dateLastModified>2016-12-20 14:02:23 CET</dateLastModified>
               <detail></detail>
               <monitoringPreference>email</monitoringPreference>
               <lastLogin></lastLogin>
        </sfuser> 
    </users>
    

    If you need to do this more often, use this script:

    #!/usr/bin/python
    
    import sys
    if len(sys.argv) != 4:
      print "This script prepends the given pattern in a template with a snippet. Both snippet and template are files."
      print "Usage:"
      print sys.argv[0] + " template snippet replacementpattern"
      sys.exit(1)
    
    template = open(sys.argv[1]).read()
    snippet = open(sys.argv[2]).read()
    pattern = sys.argv[3]
    
    if not pattern in template:
      print "Template doesn't contain the pattern."
      sys.exit(2)
    
    print template.replace(pattern, snippet + pattern)
    

    Usage:

    ./prepend.py template.xml snippet.xml "</users>"