Bash XML Parsing using Perl XPath

I have a bash script that needs to read input from an XML file, which includes varying numbers of a certain type of child node. I want to be able to iterate through all the child nodes of a given parent. I installed the Perl XML-XPath package from
search.cpan.org. Once it's installed, from bash, we can do queries like

xpath -e "//ConfigurationData/DataItem/ClassInstances/ClassInstance[1]" input.xml

This query returns the first ClassInstance node in this path. However, I don't know how to query how many nodes there of this type, or how to step through them one at a time.

Googling around, I found references to a number count() function and an fn.count() function, but couldn't get either to work inside an xpath command called from bash.

Any suggestions? Thanks!

Please supply a short example of your XML file.

The XML file is still being designed, so we have some flexibility there. I expect it to include collections with a varying number of members such as

<breads>
  <bread>
      <type>sourdough</type>
  </bread>
  <bread>
      <type>pumpernickel</type>
  </bread>
</breads>

Thanks.

My version of Perl xpath does not have a -e option and the command line syntax appears to be different. However you should be able to get the idea.

To retrieve the count of the bread nodes:

$ xpath input.xml "count(//bread)"  2>/dev/null
2
$

To retrieve the contents of the first type node:

$ xpath input.xml "//bread[position() = 1]/type/text()" 2>/dev/null
sourdough
$

To retrieve the contents of the second type node:

$ xpath input.xml "//bread[position() = 2]/type/text()" 2>/dev/null
pumpernickel
$
1 Like

Thanks, fpmurphy! Your example worked perfectly, with only a slight adjustment for the differing syntax of xpath on my system:

xpath -e "count(//bread)" input.xml 2>/dev/null

The 2>/dev/null that you included at the end is particularly nice as it suppresses some unnecessary text from the reply.

Joseph