/** * \brief XML DOM Example * * Parses an XML file from the IFS and outputs all data element names and * length from the record format elements. * *

* * The XML file must have the following path and name: * /tmp/rfml-xmldom-example.rfml * *

* * The DTD to the XML file is expected at /tmp/rfml.dtd . * The DTD can be found in the JTOpen Toolbox Jar File or at * http://www.rpgnextgen.com/downloads/rfml.dtd . * *

* * The XML Toolkit is used for parsing the string. A DOM representation of * the XML file will be created with the Xerces XML DOM parser. For any * further querying of the XML content the in memory XML DOM object is used. * This provides a fast a flexible way of accessing the XML content with * additional IO. * *

* * If the XML Toolkit has been installed the documentation for the XML * toolkit can be retrieved from the IFS at the following path: * /QIBM/ProdData/xmltoolkit2/xml5_6_0/doc/xml4pr/index.html * * \author Mihael Schmidt * \date 20.03.2009 * * \link http://www-03.ibm.com/systems/i/software/xml/index.html XML on System i * */ H dftactgrp(*no) actgrp(*caller) H ccsid(*ucs2 : 13488) *--------------------------------------------------------------- * PEP *--------------------------------------------------------------- D main PR extpgm('XMLDOM01') D main PI *--------------------------------------------------------------- * Prototypes *--------------------------------------------------------------- D printError PR * /copy QXMLDEV560/QRPGLESRC,QXML4PR560 // /copy QCPYSRC,MESSAGE *--------------------------------------------------------------- * Constants *--------------------------------------------------------------- Dtrue C 1 Dfalse C 0 Dnull C x'00' *--------------------------------------------------------------- * Variables *--------------------------------------------------------------- D rfmlFilePath S 200A D i S 10I 0 D elementName S 100A D dataCount S 10I 0 D attrValue S 50A D dataLength S 10I 0 D dataName S 20A * * XML DOM stuff * D domEnvData S * INZ(%ADDR(Qxml_DOMEXCDATA)) D parser S * D document S * D recordFormatNodeList... D S * D recordFormat S * D dataNodeList S * D data S * D dataAttributes S * D attr S * // strings are returned as unicode so we need to define a unicode variable D xmlPtr S * D xmlString S 200C based(xmlPtr) /free clear Qxml_SAXExcData; rfmlFilePath = '/tmp/rfml-xmldom-example.rfml' + null; // Initialize the XML environment, provide pointer to DOM exception // data area. A call to QxmlInit must occur before any other API // call. QxmlInit(domEnvData); // Create a new parser instance parser = QxmlXercesDOMParser_new(domEnvData); // Configure parser QxmlXercesDOMParser_setValidationScheme(parser : Qxml_VALAU); QxmlXercesDOMParser_setDoNamespaces(parser : true); QxmlXercesDOMParser_setDoSchema(parser : true); QxmlXercesDOMParser_setValidationSchemaFullChecking(parser : true); // Parse xml file QxmlXercesDOMParser_parse_SystemId(parser : %addr(rfmlFilePath) : Qxml_JOBCCSID : 0); // Check for parse error if (Qxml_ErrorType = Qxml_NOERROR or Qxml_ErrorType = Qxml_WARNING); // Get DOM document document = QxmlXercesDOMParser_getDocument(parser); // Get a node list with all record formats elementName = 'recordformat' + null; recordFormatNodeList = QxmlDOMDocument_getElementsByTagname( document : %addr(elementName) : Qxml_CHARSTR : %len(%trim(elementName))); dsply %trimr('Number of record formats: ' + %char(QxmlDOMNodeList_getLength(recordFormatNodeList))); if (QxmlDOMNodeList_getLength(recordFormatNodeList) > 0); // Get first record format recordFormat = QxmlDOMNodeList_item(recordFormatNodeList : 0); // Get a node list with data nodes in this record format elementName = 'data' + null; dataNodeList = QxmlDOMElement_getElementsByTagname( recordFormat : %addr(elementName) : Qxml_CHARSTR : %len(%trim(elementName))); dataCount = QxmlDOMNodeList_getLength(dataNodeList); dsply %trimr('Number of data elements: ' + %char(dataCount)); // Iterate through the data elements and display its names for i = 0 to dataCount - 1; data = QxmlDOMNodeList_item(dataNodeList : i); // retrieve data node attributes dataAttributes = QxmlDOMNode_getAttributes(data); // Get attribute "name" value elementName = 'name' + null; attr = QxmlDOMNamedNodeMap_getNamedItem(dataAttributes : %addr(elementName) : Qxml_CHARSTR : %len(%trim(elementName))); xmlPtr = QxmlDOMNode_getNodeValue(attr); // convert from unicode to ebcdic attrValue = %char(xmlString); dataName = %str(%addr(attrValue)); // Get attribute "length" value elementName = 'length'; attr = QxmlDOMNamedNodeMap_getNamedItem(dataAttributes : %addr(elementName) : Qxml_CHARSTR : %len(%trim(elementName))); xmlPtr = QxmlDOMNode_getNodeValue(attr); // convert from unicode to ebcdic attrValue = %char(xmlString); dataLength = %int(%str(%addr(attrValue))); // output data node name and length dsply %trimr('Node ' + %trimr(dataName) + ': ' + %char(dataLength)); endfor; else; dsply 'No record formats in this rfml file.'; endif; else; printError(); endif; QxmlTerm(); *inlr = *on; return; /end-free /** * \brief Print last XML error * * Prints the last XML error to with the error position in the XML file * to the job log. * * \todo make MESSAGE service program available */ P printError B D PI /free // sends a message to the job log // msg_sendProgramMessage('An error occured at line ' + %char(Qxml_RtnLine)+ // ' column ' + %char(Qxml_RtnCol) + '. Error: ' + // %trimr(Qxml_ErrMsg : ' ' + x'00')); dsply %trimr('XML error at %char(Qxml_RtnLine) + '/' + %char(Qxml_RtnCol) + '.'); /end-free P E