1

I have config.xml. Here I need to retrieve the value of the attribute from the xpath /domain/server/name

I can only use grep/sed/awk. Need Help

The content of the xml is below where I need to retrieve the Server Name only.

<domain>
    <server>
        <name>AdminServer</name>
        <port>1234</port>
    </server>
    <server>
        <name>M1Server</name>
        <port>5678</port>
    </server>
    <machine>
        <name>machine01</name>
    </machine>
    <machine>
        <name>machine02</name>
    </machine>
</domain>

The output should be :

AdminServer
M1Server

I tried to do,

sed -ne '/<\/name>/ { s/<[^>]*>(.*)<\/name>/\1/; p }' config.xml
jkalyanc
  • 137
  • 1
  • 2
  • 13

6 Answers6

3

sed is only for simple substitutions on individual lines, doing anything else with sed is strictly for mental exercise, not for real code. That's not what you are trying to do so you shouldn't even be considering sed. Just use awk:

$ awk -F'[<>]' 'p=="server" && $2=="name"{print $3} {p=$2}' file
AdminServer
M1Server

That will work with any awk on any UNIX box. If that's not all you need then edit your question to provide more truly representative sample input and expected output.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
2

Try this command. Name your xml and supply that file as an input.

awk '/<server>/,/<\/server>/' < name.xml | grep "name" | cut -d ">" -f2 | cut -d "<" -f1

OutPut:

AdminServer
M1Server
Ajay2588
  • 527
  • 3
  • 6
1

Based on your sample Input_file shown, could you please try following.

awk -F"[><]" '/<\/server>/{a="";next} /<server>/{a=1;next} a && /<name>/{print $3}'  Input_file
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
1
sed -n '/<server>/{n;s/\s*<[^>]*>//gp}'

for example. for the first match

1. /<server>/
match the line that contains "<server>" got "     <server>"

2. n
the "n" command will go to next line. after executed "n" command got "        <name>AdminServer</name>"

3.s/\s*<[^>]*>//gp
replece all "\s*<[^>]*>" as "". then print the pattern space

type "info sed" for more sed command

mop
  • 423
  • 2
  • 11
0

You can get the desired output with just sed:

sed -n 's:.*<name>\(.*\)</name>.*:\1:p' config.xml
0

I feel dirty parsing XML in awk.

The following finds the correct depth of entry with the right tag name. It does not verify the path, though it depends on the elements you specified. While this works on your example data, it makes certain ugly assumptions and it's not guaranteed to work elsewhere:

awk -F'[<>]' '$2~/^(domain|server|name)$/{n++} $1~/\// {n--} n==3&&$2=="name"{print $3}' input.xml

A better solution would be to parse the XML itself.

$ awk -F'[<>]' -v check="domain.server.name" '$2~/^[a-z]/ { path=path "." $2; closex="</"$2">" } $0~closex { sub(/\.[^.]$/,"",path) } substr(path,2)==check {print path " = " $3}' input.xml
.domain.server.name = AdminServer

Here it is split out for easier commenting.

$ awk -F'[<>]' -v check="domain.server.name" '
  # Split fields around pointy brackets. Supply a path to check.

  $2~/^[a-z]/ {         # If we see an open tag,
    path=path "." $2    # append the current tag to our path,
    closex="</"$2">"    # compose a close tag which we'll check later.
  }

  $0~closex {                   # If we see a close tag,
    sub(/\.[^.]$/,"",path)      # truncate the path.
  }

  substr(path,2)==check {       # If we match the given path,
    print path " = " $3         # print the result.
  }

' input.xml

Note that this solution barfs horribly if you feed it badly formatted XML. The recognition of tags could be improved, but may be sufficient if you have consistently formatted XML. It may barf horribly for other reasons too. Do not do this. Install the correct tools to parse XML properly.

ghoti
  • 45,319
  • 8
  • 65
  • 104