Creating xml stream file with CGIDEV2

Output of XML file to web browser

Once we have completed the previous html table example, we might want to try the same technique to build a json, csv or XML file. Using CGIDEV2 to build other types of files require only a few small changes. In this example, we will build on previous example to create an XML file. But first we will discuss XML a bit, because XML usage is not as commonly understood as HTML...

What is XML?
  • XML stands for EXtensible Markup Language
  • XML was designed to describe data, not to display data
  • XML is a markup language like HTML
  • XML tags are not predefined. You must define your own tags
  • XML is designed to be self-descriptive
The Difference Between XML and HTML
  • XML is not a replacement for HTML.
  • XML and HTML were designed with different goals:
    - XML was designed to describe data, with primarily focus on organizing and carrying data
    - HTML was designed to display data, with primarily focus on how data looks
XML has to be well formed...

XML Output must follow strict rules otherwise it will be rejected client reading XML document. At its base level well-formed documents require that

  • Content be defined.
  • Content be delimited with a beginning and end tag
  • Content be properly nested (parents within roots, children within parents)

To be a well-formed document, rules must be established about the declaration and treatment of entities. Tags are case sensitive (ideally in lower case), with attributes delimited with quotation marks. Empty elements have rules established. Overlapping tags will invalidate a document. Ideally, a well-formed document conforms to the design goals of XML. Other key syntax rules provided in the specification include

  • XML document contains only properly encoded legal Unicode characters.
  • None of the special syntax characters such as "<" and "&" appear except when performing their markup-delineation roles.
  • The begin, end, and empty-element tags that delimit the elements are correctly nested, with none missing and none overlapping.
  • The element tags are case-sensitive; the beginning and end tags must match exactly. Tag names cannot contain any of the characters !"#$%&'()*+,/;<=>?@[\]^`{|}~, nor a space character, and cannot start with -, ., or a numeric digit.
  • There is a single "root" element that contains all the other elements.

If you get any of the above errors, your browser will quickly let you know about it.

Back to our example

Start by creating a new XML template in IFS. We may want to use the .xml suffix in this new file (e.g: /myIFSdir/salesReportIFS.xml). In this way we can quickly identify an xml template from an html template. This naming convention is only a matter of convenience. CGIDEV2 will accept any file suffix as long as it matches the file name in RPG program. See RPG fragment that has to be changed to accomodate new template file:

 * Read externally defined template file                                              
c                   eval      IfsMultIndicators = gethtmlifsmult(                     
c                             '/myIFSdir/salesReportIFS.xml':                             
c                             '<as400>')                                              

Next, we will probably want to change the content type from Content-type: text/html to Content-type: text/xml. This is recommended but not always required because not all XML clients use this instruction. Make sure to include at least one blank line after content type. This is a CGIDEV2 requirement.

The main task we have to do to convert our html table to a xml file is make some changes to template file in the IFS. We have to remove references to html entities and replace them with XML tags. Because both the html table and XML file are used as containers for data so the conversion is pretty straightforward.

We will want to remove HTML tags (html, body, h1, table, tr, td etc...) and replace with our own custom tags (salesReport, region, regionName, sales etc...).


template for HTML table
/myIFSdir/salesReportIFS.html
<AS400>Top 
Content-type: text/html 
 
   <HTML>    
   <BODY>     
<AS400>Header1  
   <H1>Sample Sales Report for /%Year%/ 
<AS400>DataTop    
   <table border =1 >  
<AS400>DataDetail     
   <tr><td> 
   /%Region%/ </td><td > /%Sales%/  
   </td></tr> 
<AS400>DataBottom 
   </table>   
<AS400>End 
   </BODY> 
template for XML file
/myIFSdir/salesReportIFS.xml
<AS400>Top
Content-type: text/xml 

<AS400>DataTop
    <salesReport>   
<AS400>DataDetail   
       <region>   
          <regionName>/%Region%/</regionName> 
          <sales>/%Sales%/</sales>       
       </region>  
<AS400>DataBottom
    </salesReport>    
<AS400>End

Finally when we run the RPG program in the browser, we should get the output shown on the top right side of this page.



OK now what do I do with this?

XML files are often used to move data across applications. For example, here is a discussion of parsing an XML in a web browser using javascript.



What if I want to write XML to a file instead of streaming it to a browser?

Instead of sending the html buffer to the client, we can route the output to a file on IFS using the CGIDEV2 WrtHtmlToStmf procedure. This command can be useful if we want to email or FTP the file to another application, or to create a .csv file.

To write XML file discussed abovefile file on IFS, we would make the following changes to our RPG program...

D* add a new variable to tell the program where on IFS to put your stream file
D  Stmf           s            512    varying
D                                     inz('/myIFSXMLLib/salesReportIFS.xml')

D* create a return code variable
D  rc             s             10i 0
 .
 .
 .
C** remove the write section *fini. This is the section prompts program to return stream file to client's browser.
C**                 callp     wrtsection('*fini') 

C* instead we want to stream it to file specified above using the WrtHtmlToStmf or AppHtmlToStmf
C                   eval      rc = WrtHtmlToStmf(Stmf)