Hackday 9 - REXX, Java and XML

Автор: Martin Packer

Дата: 10.10.2011

Источник: IBM developerWorks

I've written about Hackday in the past. See My HackDay 6 Project - Mashing Up RMF, My HackDay 5 Project - z/OS System Logger Analysis and Hackday4 and Referer URLs (though I don't know why I didn't write about Hackday 7 or Hackday 8).
 
So, this year I participated in Hackday 9 (last Friday). My entry follows on from this recent blog post: BPXWUNIX - z/OS' Best Kept Secret?. Graham Harris, in his comment, mentions using java to process XML (albeit with issues with the XML generated by RMF, caused by the 2048 byte record limit of BPWUNIX). I'd been thinking along similar lines, though not RMF output specifically.
 
So my entry has at its core a java program that uses standard functionality to process XML. In particular I pass a filename and an XPath expression in to the java program and it returns the results of evaluating the expression. I intend it as a sample, rather than a really useful program - but I think it COULD be used.
 
I call the java program from REXX using BPXWUNIX. There is a wrinkle here. I'd not realised it before but you can pass in environment variables. Here's the REXX:
 

/* REXX */
                                                                   
/* Set up environment - else java executable can't be found */
env.0=1
env.1="PATH=/bin:.:/usr/lpp/java/J5.0/bin:."
                                                                   
/* No standard input lines in this case */
stdin.0=0
                                                                   
/* XML file name */
ifn="test4.xml"
                                                                   
/* XPath expression to evaluate */
XPathExpression="//book[author='Neal Stephenson']/title/text()"
                                                                   
/* Execute java program with XML file name and XPath expression */
cmd='java XPathEvaluator.class' ifn '"'XPathExpression'"'
call bpxwunix cmd,stdin.,stdout.,stderr.,env.
                                                                   
say "stdout:"
say "======="
do i=1 to stdout.0
  say i stdout.i
end
                 
say "stderr:"
say "======="
do i=1 to stderr.0
  say i stderr.i
end

Apart from the "env" lines at the top (and the extra parameter to BPXWUNIX) and the java command this is exactly the same as code as in BPXWUNIX - z/OS' Best Kept Secret? and so needs no explanation.
 
Here's the XML file we're processing, so the XPath expression makes sense.
 
<?xml version="1.0"?>
<inventory>
  <book year="2000">
    <title>Snow Crash</title>
    <author>Neal Stephenson</author>
    <publisher>Spectra</publisher>
    <isbn>0553380958</isbn>
    <price>14.95</price>
  </book>
  <book year="2005">
    <title>Burning Tower</title>
    <author>Larry Niven</author>
    <author>Jerry Pournelle</author>
    <publisher>Pocket</publisher>
    <isbn>0743416910</isbn>
    <price>5.99</price>
  </book>
  <book year="1995">
    <title>Zodiac</title>
    <author>Neal Stephenson</author>
    <publisher>Spectra</publisher>
    <isbn>0553573862</isbn>
    <price>7.50</price>
  </book>
  <!-- more books... -->
</inventory>

In the XPath expression we look for the text in the title element of each of the book elements whose author element's value is "Neal Stephenson". (I got this XML and much besides, by the way, from The Java XPath API - Querying XML from Java programs. The result of evaluating the expression is:

stdout:   
=======   
1 Snow Crash
2 Zodiac  
stderr:   
=======   
and this is because only two of the book elements match the [author="Neal Stephenson] condition.
 
The java to drive this is:
 
import java.io.*;
                                                                   
import org.w3c.dom.*;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
                                                                   
public class XPathEvaluator{
                                                                   
  public static void main(String args[]) throws Exception{
    DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
                                                                   
    DocumentBuilder docBuilder=dbf.newDocumentBuilder();
                                                                   
    Document doc=docBuilder.parse(new FileInputStream(args[0]));
                                                                   
    XPathFactory xpf=XPathFactory.newInstance();
    javax.xml.xpath.XPath xp=xpf.newXPath();
                                                                   
    XPathExpression expr=xp.compile(args[1]);
                                                                   
    Object result=expr.evaluate(doc,XPathConstants.NODESET);
    NodeList nodes = (NodeList) result;
     for(int i=0;i<nodes.getLength();i++) {
       System.out.println(nodes.item(i).getNodeValue());
     }
   }
 }

This is also largely described here.
 
So you have the sample REXX, java and XML to play with. A couple of things I would note:
    * There is only one pair of "boundary crossings" between REXX and java - which is, I think, goodness.
    * Because the XML parsing is done in java (through XALAN-J) I expect this to be very largely zAAP-eligible. Another nice characteristic.

 One final thing: If you search in my blog you'll see I mention XPath in Workload Manager Policy in XML Format - Part I and Workload Manager Policy in XML Format - Part III.

Happy hacking!