Tuesday, 26 August 2014

Quick and dirty XML in shell

I found myself helping a colleague having fun trying to get various bits of XML data out of a WebSphere config file today, I knocked this up as a quick way to list the data and hopefully be adapted to his requirements. I'm sure theres better ways of doing this, and feel free to suggest improvements or links to other better ways to parse XML in shell (obviously there various ways with CPAN, or xmllint but as you may have gathered my current workplace is locked down with minimal amounts of useful tools!).


for each in $(cat ./test.xml | sed "s/</ </g;s/>/> /g" | tr -d "\n")
do
  #echo "INPUT: [$each]"
  # Create a plain text string version of each
  temp=$(echo $each | tr -d "<>")

  # Check if its an attrib or data, or an element name
  if [[ $(echo $each | cut -c 1-2) == "</" ]]; then
   #its an </end> tag
   echo "ELEMENT END: [$temp]"
  elif [[ $each == "/>" ]]; then
   #its a self contained <end /> tag
   echo "ELEMENT END: [$lastElement]"
  elif [[ $(echo $each | cut -c 1) == "<" ]]; then
   #if it starts with a < and isn't either of the above
   #then its a <begin> tag
   echo "ELEMENT BEGIN: [$temp]"
   lastElement=$temp
  else
   #its either data or an attribute
   attribValue=$(echo $temp | cut -d= -f2 )
   attribName=$(echo $temp | cut -d= -f1 )
   if [[ $attribValue != $attribName ]]; then
    #it must be an attribute on an element
    echo "AttribName: $attribName"
    echo "AttribVal : $attribValue"
   else
    #it must be data
    echo "Data: $each"
   fi
   unset attribName
   unset attribValue
  fi
done

Of course, if you do have tools like xmllint to hand...

To find a port in the server index file —


#!/bin/bash

WASBASE=${2:-"/opt/IBM/WebSphere"}


for each in $(find $WASBASE -name serverindex.xml | grep -iv Templates)
do
xmllint --shell $each <<<"xpath //specialEndpoints[contains(@endPointName,'$1')]/endPoint/@port" | grep "=" | cut -d"=" -f2
done

No comments: