0

I have an xml file to find and replace a line where there is url which is linked to where the Resource name = "java/RulesPlugin"

The issue is that sometimes the <Resource name="java/RulesPlugin" might be out of sequence and not in the first line. I was only able to find the example.co.uk if the Resource name = "java/RulesPlugin" is first in the list but I need to be able to filter where the url is with <Resource name="java/RulesPlugin" no matter the location or sequence in that file.

script :

grep -oPm1 '(?<=url="jdbc:postgresql://)[^<]+' <  test.xml | sed -r 's/^.{0}//' | sed 's/^[[:space:]]*//' |   cut -d: -f1
varurl=`grep -oPm1 '(?<=url="jdbc:postgresql://)[^<]+' <  test.xml | sed -r 's/^.{0}//' | sed 's/^[[:space:]]*//' |   cut -d: -f1`
echo "${varurl}"        
sed -i -e "0,/$varurl/ s/$varurl/newstring-replace.co.uk/g" test.xml

If the xml content with <Resource name="java/RulesPlugin" is not the first in the list but is down in the middle randomly. How can I use bash to get this same result?

 <?xml version="1.0"?>
    
    <Context>
    <Resource name="java/RulesPlugin"
          auth="Container"
          type="javax.sql.DataSource"
          driverClassName="org.postgresql.Driver"
          url="jdbc:postgresql://example.co.uk:5000/sandbox"
          user="xxxx"
          token="xxxxx"
          maxActive="100" 
          maxIdle="30" 
          maxWait="10000"
    
      />
      
      <Resource name="java/Reports"
          auth="Container"
          type="javax.sql.DataSource"
          driverClassName="org.postgresql.Driver"
          url="jdbc:postgresql://example.co.uk:5000/sandbox"
          user="xxxx"
          token="xxxxx"
          
     />
      <Resource name="java/Balancer"
          auth="Container"
          type="javax.sql.DataSource"
          driverClassName="org.postgresql.Driver"
          url="jdbc:postgresql://example.co.uk:5000/sandbox"
          user="xxxx"
          token="xxxxx"
    
     />

UPDATE: Thanks for all the answers, some do work on the local unix, but I really need xml tool to work with Jenkins pipeline.

user5820327
  • 181
  • 1
  • 2
  • 15

3 Answers3

1

It can be done with xmllint (present on most distros) as below. New value must be set on url variable

url="jdbc://asdasdas" echo -e "cd /Context/Resource[@name='java/RulesPlugin']/@url\nset $url\nsave\nbye") |  xmllint --shell tmp.xml
/ > cd /Context/Resource[@name='java/RulesPlugin']/@url
url > set jdbc://asdasdas
url > save
url > bye

As the output shows, 4 commands were pass to xmllint --shell

/ > cd /Context/Resource[@name='java/RulesPlugin']/@url
url > set jdbc://asdasdas
url > save
url > bye

Alternatively and assuming XML format is in the provided format regardless of attributes order, it could be done with awk as

url='url="jdbc:postgresql://example.com:7777/sandbox"'
gawk -v url="$url" '
    BEGIN{RS="[/]>\n"; FS="\n"; OFS="\n"}
    {
        if (NR==1 && $0 ~ /java[/]RulesPlugin/){
            for(i=1; i<=NF; i++) {
                if($i ~ /url=/) $i = url
            }
            print $0 "/>"
        } else {
            print $0 "/>"
        }
}' tmp.xml

And with sed as

tr -d '\n' < tmp.xml | sed -re 's/^(.*Resource name="java\/RulesPlugin" [^>]+  url=")([^=" ]+)(" [^>]+ *[/]>.*)/\1NEWURL\3/'
LMC
  • 10,453
  • 2
  • 27
  • 52
  • Thank you. I would prefer to use sed instead as this is not just bash and will make use of this in Jenkins pipeline. I want something along the line of using grep or sed – user5820327 Aug 26 '22 at 18:48
  • @user5820327 provided option with awk and sed. – LMC Aug 26 '22 at 19:10
1

This might work for you though parsing xml with sed is not a robust method.

sed '/Resource name="java\/RulesPlugin"/,/\/>[[:blank:]]*$/{
     /\(.*url="jdbc:postgresql:\/\/\)[^:/]*/s//\1newstring-replace.co.uk/
}' test.xml
M. Nejat Aydin
  • 9,597
  • 1
  • 7
  • 17
0

Please don't use inappropriate tools to parse XML! An XML-parser like would be more suited:

$ xidel -s test.xml -e '
  x:replace-nodes(
    Context/Resource[@name="java/RulesPlugin"]/@url,
    attribute url {"newstring-replace.co.uk"}
  )
' --output-format=xml --output-node-indent
Reino
  • 3,203
  • 1
  • 13
  • 21