Store Tags of XML File in an Array Using Shell Script

Viewed 113

I have an XML file of the format:

<classes>

 <subject>
  <name>Operating System</name>
  <credit>3</credit>
  <type>Theory</type>
  <faculty>Prof. XYZ</faculty> 
 </subject>

 <subject>
  <name>Web Development</name>
  <credit>3</credit>
  <type>Lab</type>
 </subject>

</classes>

I want to store the tag names i.e. name, credit, type, faculty in an Array using Shell Script.

I tried using awk command as:

awk -F'[<>]' '/<name>|<credit>|<type>|<faculty>/{print $2}' file.xml

But it's returning values as:

name
credit
type
faculty
name
credit
type

How to store these results in an array?

2 Answers

If you control the source of the xml, I understand the temptation to pares it by hand. But there's a lot that can go wrong with that approach. It's safer to use an xml library to parse xml.

Here's a way using libxml with its command line interface, xsltproc:

xsltproc classes.xsl classes.xml

classes.xsl:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="text" />
    <xsl:strip-space elements="*" />

    <xsl:template match="/classes/subject/*">
        <xsl:text>&#x09;</xsl:text>
        <xsl:value-of select="name(.)" /><xsl:text>:&#x09;</xsl:text>
        <xsl:value-of select="." /><xsl:text>&#x0a;</xsl:text>
    </xsl:template>

    <xsl:template match="/classes/subject/name">
        <xsl:text>'</xsl:text>
        <xsl:value-of select="." />
        <xsl:text>':&#x0a;</xsl:text>
    </xsl:template>
</xsl:stylesheet>

input:

<?xml version="1.0"?>
<classes><subject><name>Operating System</name><credit>3</credit><type>Theory</type><faculty>Prof. XYZ</faculty></subject><subject><name>Web Development</name><credit>3</credit><type>Lab</type></subject></classes>

output:

'Operating System':
    credit: 3
    type:   Theory
    faculty:    Prof. XYZ
'Web Development':
    credit: 3
    type:   Lab

When I was slicing and dicing xml, someone took the time to explain this to me. Now I'm paying it forward.

result=($(awk -F'[<>]' '/<name>|<credit>|<type>|<faculty>/{print $2}' file.xml))
resultlen=${#result[@]}
echo "resultlen size: ${resultlen}"

for i in "${!result[@]}";
do 
    echo "Tags ${i} : ${result[i]}"
done
Related