LinuxQuestions.org
LinuxAnswers - the LQ Linux tutorial section.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices

Reply
 
Search this Thread
Old 11-17-2011, 10:25 AM   #1
nano2
Member
 
Registered: May 2007
Posts: 100

Rep: Reputation: 15
Adding new tag to an xml file using sed


Hi

Have an xml file where by i want to add a tag and its value to it


BEFORE :

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC
        "-//Sun Microsystems, Inc.//DTD"
        "http://java.sun.com/dtd/ab.dtd">


<app>

    <bbb>
        <jjj>test1</jjj>

     </bbb>

     <bbb>   
       <jjj>test2</jjj>
    </bbb>

    <bbb>
        <jjj>test3</jjj>
    </bbb>

</app>
AFTER :

Code:
</app><?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC
        "-//Sun Microsystems, Inc.//DTD"
        "http://java.sun.com/dtd/ab.dtd">

<app>

    <bbb>
        <jjj>test1</jjj>

     </bbb>

     <bbb>   
       <data>test2</data>
    </bbb>


    <bbb>   
       <jjj>test2</jjj>
    </bbb>
       
   

    <bbb>
        <jjj>test3</jjj>
    </bbb>
  

</app>



i was trying to do was to use sed to add the new tag <data>

Code:
FILE=~/test.xml

sed -i.bck 's#\(app\).*\(;/app\)#\1<bbb>   
       <data>test2</data>
    </bbb>\2#g' $FILE

This however does not work any ideas ?
 
Old 11-17-2011, 11:03 AM   #2
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948
Could you explain in more detail your exact requirements? why are you trying to substitute "app", etc...? Are you really trying to run the substitution on the whole section?

sed is not a very good multi-line editor, and only operates on one line at a time by default. Targeting multi-line blocks often requires complex handling.

What we really need to know is, what defines the line that needs to be changed?

If it's the content of the tag, for example, you may really only need something like this:

Code:
sed '\|test2| s|jjj|data|g' file
Or if you need it to be more accurate, and specifically target the tag itself, perhaps this:
Code:
sed -r '\|test2| s|<(/?)[^>]+>|<\1data>|g' file
But if you need it to match something only within a certain sub-section of lines or something, that's more difficult, and maybe even close to impossible. So again, we need you do define the problem more exactly. If the necessary operation is much more complex than a simple text-matching, then you may have to turn to a different tool that's capable of doing true xml parsing and editing.

Considering that xml structure is free-form and can easily span multiple lines, that may be a good idea in any case.

Last edited by David the H.; 11-17-2011 at 11:05 AM. Reason: minor rewording
 
Old 11-18-2011, 03:14 AM   #3
nano2
Member
 
Registered: May 2007
Posts: 100

Original Poster
Rep: Reputation: 15
I want to insert the tag below there is no replacement needed I want the tag below slotted in betweenthe tags <app> </app>


<bbb>
<data>test2</data>
</bbb>
 
Old 11-18-2011, 12:25 PM   #4
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948
Ah, ok. I failed to see that it was a separate insert. I thought you were just modifying the tags already there.

sed has the dedicated commands -i (insert before), and a (append after) for adding lines of text to a file, instead of substitution. The following will append the desired section directly after the <app> tag.

Code:
sed '\|<app>| a \
\n\t<bbb>\n\t\t<data>test2</data>\n\t</bbb>
' file
If you need it to go in exactly the place shown in the output above, then you need to use nesting to target the first </bbb> after <app>.

Code:
sed '\|<app>|,\|</app>| { \|</bbb>| a \
\n\t<bbb>\n\t\t<data>test2</data>\n\t</bbb>
}' file
Note the multi-line nature of the a and i text. You need to separate out the text block to insert with the initial slash+newline and final raw newline (also backslash any other literal newlines before the last one). gnu sed is a little more flexible than some other versions on this, but for larger blocks of text it's probably safer just to use them anyway.

http://www.grymoire.com/Unix/Sed.html
http://sed.sourceforge.net/grabbag/
http://sed.sourceforge.net/sedfaq.html
http://sed.sourceforge.net/sed1line.txt


I still say it would be better to use a tool that's designed specifically for editing xml. This one looks like it may be useful, for example:

http://xmlstar.sourceforge.net/overview.php

Or at the very least you could the file through xmllint to clean up the formatting first.

Last edited by David the H.; 11-18-2011 at 12:35 PM. Reason: minor clarification
 
Old 11-22-2011, 08:38 AM   #5
nano2
Member
 
Registered: May 2007
Posts: 100

Original Poster
Rep: Reputation: 15
Code:
sed '\|<app>|,\|</app>| { \|</bbb>| a \
\n\t<bbb>\n\t\t<data>test2</data>\n\t</bbb>
}' file
This appended after each <bbb> tag element i just want it enter once ....
 
Old 11-23-2011, 05:35 AM   #6
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948Reputation: 1948
Well then, this just illustrates exactly why sed isn't the proper tool to use. It's not really designed for editing things like xml files. How many times do I have to suggest that you find a true xml parser for this?

I don't know why I was thinking it would only append to the first instance, but I certainly was wrong about it. I can't think now, offhand, of any easy way to limit it to only one match. Sorry.
 
Old 11-23-2011, 05:47 AM   #7
jschiwal
Guru
 
Registered: Aug 2001
Location: Fargo, ND
Distribution: SuSE AMD64
Posts: 15,733

Rep: Reputation: 654Reputation: 654Reputation: 654Reputation: 654Reputation: 654Reputation: 654
Code:
sed '/<bbb>/,/<\/bbb>/{
                        /<jjj>test2<\/jjj>/s#<jjj>test2</jjj>#<data>test2</data>#
                      }' test.xml
To select a range of lines, use pattern selection: /pattern1/,/pattern2/{ .. }
The sed commands inside the braces will only be run inside the range of lines matching the pattern. You can have ranges
inside ranges.

You may need to add another line for the case when the xml tag is contained in the same line.

When working with xml, an xslt transform may be a better way to go.
 
  


Reply

Tags
bash scripting, bash sed find


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] sed used to remove a line from xml file nano2 Linux - General 6 10-25-2011 06:30 AM
how to find the end tag in xml file. mariakumar Linux - General 1 12-21-2010 10:12 AM
How to find the tag value in xml file through unix shell script hussain.s Linux - General 2 11-03-2010 07:52 AM
Remove sections of a xml file with sed viniciusandre Linux - Software 2 04-20-2009 01:18 PM
How To get the data from a tag in XML File kingmaker2003 Programming 7 12-04-2008 11:12 PM


All times are GMT -5. The time now is 06:11 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration