how to edit XML using bash script? how to edit XML using bash script? bash bash

how to edit XML using bash script?


To change tag's value to 2 and tag1's value to 3, using XMLStarlet:

xmlstarlet ed \  -u '/root/tag' -v 2 \  -u '/root/tag1' -v 3 \  <old.xml >new.xml

Using your sample input:

xmlstarlet ed \  -u '/root/tag' -v 2 \  -u '/root/tag1' -v 3 \  <<<'<root><tag>1</tag><tag1>2</tag1></root>'

...emits as output:

<?xml version="1.0"?><root>  <tag>2</tag>  <tag1>3</tag1></root>


You can use the xsltproc command (from package xsltproc on Debian-based distros) with the following XSLT sheet:

<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  <xsl:output method="xml" indent="yes"/>  <xsl:param name="tagReplacement"/>  <xsl:param name="tag1Replacement"/>  <xsl:template match="node()|@*">    <xsl:copy>      <xsl:apply-templates select="node()|@*"/>    </xsl:copy>  </xsl:template>  <xsl:template match="tag">    <xsl:copy>      <xsl:value-of select="$tagReplacement"/>    </xsl:copy>  </xsl:template>  <xsl:template match="tag1">    <xsl:copy>      <xsl:value-of select="$tag1Replacement"/>    </xsl:copy>  </xsl:template></xsl:stylesheet>

Then use the command:

xsltproc --stringparam tagReplacement polop \         --stringparam tag1Replacement palap \         transform.xsl input.xml

Or you could also use regexes, but modifying XML through regexes is pure evil :)


my $0.02 in python because its on every server you will ever log in to

import sys, xml.etree.ElementTree as ETdata = ""for line in sys.stdin:    data += linetree = ET.fromstring(data)nodeA = tree.find('.//tag')nodeB = tree.find('.//tag1')tmp = nodeA.textnodeA.text = nodeB.textnodeB.text = tmp print ET.tostring(tree)

this reads from stdin so you can use it like this:

$ echo '<node><tag1>hi!</tag1><tag>this</tag></node>' | python xml_process.py <node><tag1>this</tag1><tag>hi!</tag></node>

EDIT - challenge accepted

Here's a working xmllib implementation (should work back to python 1.6). As I thought it would be more fun to stab my eyes with a fork. The only think I will say about this is it works for the given use case.

import sys, xmllibclass Bag:    passclass NodeSwapper(xmllib.XMLParser):    def __init__(self):    print 'making a NodeSwapper'    xmllib.XMLParser.__init__(self)    self.result = ''    self.data_tags = {}    self.current_tag = ''    self.finished = False    def handle_data(self, data):    print 'data: ' + data    self.data_tags[self.current_tag] = data    if self.finished:       return    if 'tag1' in self.data_tags.keys() and 'tag' in self.data_tags.keys():        b = Bag()        b.tag1 = self.data_tags['tag1']        b.tag = self.data_tags['tag']        b.t1_start_idx = self.rawdata.find(b.tag1)        b.t1_end_idx = len(b.tag1) + b.t1_start_idx        b.t_start_idx = self.rawdata.find(b.tag)        b.t_end_idx = len(b.tag) +  b.t_start_idx         # swap        if b.t1_start_idx < b.t_start_idx:           self.result = self.rawdata[:b.t_start_idx] + b.tag + self.rawdata[b.t_end_idx:]           self.result = self.result[:b.t1_start_idx] + b.tag1 + self.result[b.t1_end_idx:]        else:           self.result = self.rawdata[:b.t1_start_idx] + b.tag1 + self.rawdata[t1_end_idx:]           self.result = self.result[:b.t_start_idx] + b.tag + self.rresult[t_end_idx:]        self.finished = True    def unknown_starttag(self, tag, attrs):    print 'starttag is: ' + tag    self.current_tag = tagdata = ""for line in sys.stdin:    data += lineprint 'data is: ' + dataparser = NodeSwapper()parser.feed(data)print parser.resultparser.close()