Parsing XML with XMLParse and XPath

If you need to extract data from XML using  Macro Scheduler you can use the built in XMLParse function.

XMLParse allows you to use  XPath syntax to specify which piece of information from the XML you want to retrieve.

To demonstrate how it works lets start with a simple XML example. Consider this XML:

<?xml version="1.0" encoding="UTF-8"?>
 
<bookstore>
 
<book category="COOKING">
  <title lang="en">Everyday Italian</title>
  <author>Giada De Laurentiis</author>
  <year>2005</year>
  <price>30.00</price>
</book>
 
<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>
 
<book category="WEB">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
</book>
 
<book category="WEB">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
</book>
 
</bookstore>

XMLParse takes this syntax:

XMLParse>XML,XMLPath,result_string,num_items

XMLParse takes an XPath specification to identify the element we want to get information from, a result variable to put the result in, and another variable to store the number of items found. A good place to find out how XPath works is  here. I'm not going to replicate XPath documentation here. Instead we'll look at some examples which should help understand it, which you can look it while also referring to the w3schools link above.

So let's see how we could retrieve all the book titles in the above XML.  Before we do anything of course we need to have retrieved this XML from somewhere.  It may be the result of an HTTPRequest call, but for now let's assume it's in a file and we've retrieved it to a string variable called strXML using the ReadFile command.

First we need to get the number of books:

XMLParse>strXML,/bookstore/book,val,numBooks

Notice how we construct a path to the node (or nodes) we are interested in starting at the root with /.  Our "book" elements are within the "bookstore" node. So to get to them we use /bookstore/book.  For more info on  XPath Syntax look here

numBooks now contains the number of elements that match.  Once we have that we can loop through each one:

Let>k=0
Repeat>k
  Let>k=k+1
  XMLParse>strXML,/bookstore/book[%k%]/title/text(),val,len
  MessageModal>val
Until>k=numBooks

Notice we specify the index within [ and ] after the node and use text() to tell XPath to retrieve the text of the element - that's the bit in between the opening and closing tags.  If we just wanted to retrieve the first book we could have used /bookstore/book[1] but here we've constructed a loop for each book so we are specifying our loop counter k: /bookstore/book[%k%]

Now, this is all very well, but what if we want to specify a bit more detail. Let's say we only want to retrieve only books in the "WEB" category (category="WEB"). To do this we can use the attribute specifier:

XMLParse>strXML,/bookstore/book[@category='WEB'],val,numBooks

Notice how we use the [@attribute='value'] syntax after the node name.  So here we are looking for the number of book elements with the "category" attribute set to "WEB".  In other words, all the books in the web category.  Note that the value (WEB) needs to be in single quotes.

So we modify our loop in a similar way:

Let>k=0
Repeat>k
  Let>k=k+1
  XMLParse>strXML,/bookstore/book[@category='WEB'][%k%]/title/text(),val,len
  MessageModal>val
Until>k=numBooks

We're still using a loop counter - after the [@category='WEB'] identifier we specify the index of the item to retrieve.

We can use the @attribute syntax in a similar way if we want to retrieve the value of an attribute, instead of the text() component as above. E.g. look at the title nodes in the XML.  Notice they have a "lang" attribute for the language of the book.  Let's say we want to retrieve this value to see what language our books are, as well as the title.  We could add:

XMLParse>strXML,/bookstore/book[@category='WEB'][%k%]/title/@lang,sLang,len

So instead of text() we have @lang.  Our result variable sLang will now contain the value of this attribute (in our case always "en").

So our full code becomes:

XMLParse>strXML,/bookstore/book[@category='WEB'],val,numBooks
Let>k=0
Repeat>k
  Let>k=k+1
  XMLParse>strXML,/bookstore/book[@category='WEB'][%k%]/title/text(),val,len
  XMLParse>strXML,/bookstore/book[@category='WEB'][%k%]/title/@lang,sLang,len
  MessageModal>%val% (%sLang%)
Until>k=numBooks

For another example using this kind of syntax take a look at  this recent forum post.

Still need help? Contact Us Contact Us