XML Tools


XML Parsers

Parsing is at the core of any XML application.  Behind the scenes of an XML application there is a parser that takes data and puts it in a format that the application can understand.

There are two types of XML parsers: those that validate documents and those that just ensure that the document is well formed.  A validating parser ensures that the document conforms to the DTD specified within it -- for SPAN XML files it would be the spanrisk.dtd file.   A nonvalidating parser simply checks that the document is well-formed, i.e. begins with an XML declaration ( e.g. <?xml version="1.0"?> ) and contains properly nested and marked-up elements.  Validating parsers tend to be much larger than nonvalidating parsers and require more RAM and processing power.

One of the best available free tools to view XML files is Microsoft® XML Notepad that can be downloaded from the web.  It is based on a nonvalidating parser.  With XML Notepad, developers can quickly create XML prototypes in an iterative mode.  It offers an intuitive and simple user interface that graphically represents the tree structure of XML data.  This tool can be used to view any XML files, and we definitely would recommend it for quick checking and browsing of SPAN XML files outside the PC-SPAN 4 environment.

For more thorough checking of XML data, a validating parser should be used.  XML <PRO>  --  an XML editor from Vervet Logic is one of the first tools of this type available on the market.  It combines the power of XML with an intuitive user interface that allows users to easily create and edit XML-based documents, regardless of previous experience with XML.

The Microsoft®  MSXML Parser is a validating XML parser written in Java. The parser checks for well-formed documents and optionally permits checking of the documents' validity against a DTD. Once parsed, the XML document is exposed as a tree through a simple set of Java methods.  There is also a nonvalidating version of this parser written in C++.  It is optimized for speed and efficiency and is distributed as an ActiveX control with IE4.

IBM supports an extensive web site devoted to XML.   It offers a number of XML development tools including a free validating XML parser written in Java. The package (com.ibm.xml.parser) contains classes and methods for parsing, generating, manipulating, and validating XML documents.


Web Browsers

Microsoft IE4 was the first browser to support XML.  To accomplish this, IE4 uses the external MSXML parser that can break a document's XML tags into an object tree.  Values contained in structured tag sets are exposed as objects that can be manipulated within the browser by JavaScript.  The next generation of browsers, however, will natively recognize and parse XML documents. 

Microsoft IE 5 Beta features significant updates to the XML-related components offered in IE 4.0. It supports the following key features:

The first version of Netscape browser to support XML will be version 5.  Netscape has already committed to displaying native XML documents in Navigator and Communicator 5.0 browsers.


JavaScript Example

Since the XML data can be represented in the browser's object model, it is possible to write a script to manipulate and display the data.  At this time, however, even in IE4, in order to load an XML file, you need to use the MSXML ActiveX control.

The following example shows how, for example, a JavaScript can be used to manipulate a SPAN XML file to generate a Currency Conversion report.  This is a simplified version of the actual script that is used in PC-SPAN version 4 to produce an XML-based report.  It takes into account a specific XML file structure described in the spanrisk.dtd file.

The script first creates an ActiveX object representing a MSXML parser.  Then it loads an XML file, parses it, and passes the root of the XML document to the makeReport functionHaving the root element, it is quite easy to get any XML element in question and its value and then to dynamically generate a report.  At the end, the script writes the entire HTML to the document.  To run this script, you need to have IE4 installed on your system.

<SCRIPT LANGUAGE="JavaScript">
    // Create an ActiveX object representing an XML document
    var objXml = new ActiveXObject("MSXML");

    // Specify a SPAN XML file to parse
    objXml.URL = "http://www.cme.com/span/span4_xml_default.xml";
    // Get the root object
    var root = objXml.root;
    
    // Make the report
    var content;
    if ( root != null)
        content = makeReport(root)
    else 
        content = "<P>Can't get the root element</P>";
    
    // Write the entire HTML to the document    
    document.write(content);

function makeReport(elem)
// Given the root element, returns a specific report
{
    // get <pointInTime> and <clearingOrg> objects
    elem = getElement(elem, "pointInTime");
    if (elem == null) return "<P class=error>Can't find &lt;pointInTime&gt;";
        date = getElementValue(elem, "date");
        isSetl = getElementValue(elem, "isSetl");
        setlQualifier = getElementValue(elem, "setlQualifier");
        run = getElementValue(elem, "run");
    elem = getElement(elem, "clearingOrg");
    if (elem == null) return "<P class=error>Can't find &lt;clearingOrg&gt;";
        ec = getElementValue(elem, "ec");

    // get a collection of <curConv> elements
    elem = getElement(elem, "curConv");
    if (elem == null) return "<P class=error>Can't find &lt;curConv&gt;";
    
    // for each <curConv> element
    var content = "";
    for (var i = 0; i < getSize(elem); i++) {
        var obj = getElemFromCol(elem,i);
        content += "<TR><TD>"
            + getElementValue( obj, "fromCur" )
            + "</TD><TD>"
            + getElementValue( obj, "toCur" )
            + "</TD><TD>"
            + getElementValue( obj, "factor" )
            + "</TD></TR>";
            ;
    }
    var headings = 
        "<TR><TH>From Currency</TH><TH>To Currency</TH><TH>Conversion Rate</TH></TR>";

    return ( "<TABLE>" + headings + content + "</TABLE>" );
}        

function getElement(obj, tagName) {
// Returns a requested element from a container
    if (obj == null || tagName == null) 
        return null;
    tagName = tagName.toUpperCase();
    var children = obj.children;    // get all children
    if (children != null) {
        // check if a requested element is among children
        for (var i = 0; i < children.length; i++) {
            if (children.item(i).tagName == tagName)
                return obj.children.item(tagName);
        }
        return null;            
    } else
        return null;
}

function getElementValue(elem, tagName) { 
// Returns an element's attribute value
    elem = getElement(elem, tagName);
    if (elem != null) 
        return elem.text;
    else
        return "n/a";
}

function getSize(elem) {
// Returns a collection size
    if (elem == null) return null;
    else if (elem.length > 1) return elem.length;
    else return 1;
}    

function getElemFromCol(elem, i) {
// Returns an element from a collection at index 'i'
        if (getSize(elem) > 1) return elem.item(i);
        else return elem;
}    

</SCRIPT>

MS Access Example

All major database venders are working on tools to facilitate import/export data to/from databases that will become available in the forthcoming upgrades.  At the mean time, however, we can address an issue of importing data from an XML file into a MS Access database in a similar manner to what we did in the JavaScript example.

The following example demonstrates how to import data from an XML file to an Access database.  In this particular case, we will extract Currency Conversion data from a sample Span XML file and populate a Currency Conversion Rates table.  To run this example, you will need to download the file span4_xml_access.zip (that contains an Access .mdb file and a sample XML file) to your local drive, unzip it, and then open an .mdb file.  The 'Action...' menu on the first screen gives you a choice of parsing an XML file and populating a Currency Conversion Rates table.  In any case, you will need first to chose an XML file to parse -- specify the sample XML file that comes with this example.  Other menu choices allow to view prebuild forms and reports.

The following excerpt of a VBA code from this example explains the details of exporting data from an XML format to an Access database.  The first step is to create an ActiveX object representing a MSXML parser.  Then we need to parse an XML file of interest and get the root of the XML document.  Having the root element, it is quite easy to get any XML element in question and its value and then to dynamically populate the database.  To run this example, you need to have a MSXML parser (that comes with IE4) installed on your system.  The VBA code is very similar to the code in the JavaScript example, and it can be easily elaborated to populate a database of any complexity.

    Option Compare Database
    Option Explicit
    Public root As Object     'XML  file root  object
    Public FileName As String 'XML file to parse
  
Function parseXmlFile() As Object

  'Create an ActiveX object representing an XML document
    Dim xml As Object
    Set xml = CreateObject("msxml")

  'Specify the SPAN XML file to parse
    DoCmd.OpenForm ("CommonDialog")
    DoCmd.Close acForm, "CommonDialog"
    xml.URL = FileName

  'Get the root object
    Set root = xml.root

    If Not root Is Nothing Then
        MsgBox "Successfully parsed XML file " + FileName
    Else
        MsgBox "Failed to parse XML file " + FileName
    End If

  'Set a return value
    Set parseXmlFile = root

End Function

Function updateCurConvTable()
    
  'Check if an XML file has already been parsed
    If root Is Nothing Then
        Set root = parseXmlFile()
    End If
    
    Dim elem As Object
  
  'Get "pointInTime" and "clearingOrg" objects
    Set elem = root.Children.Item("pointInTime")
        Dim busDate As String
        busDate = elem.Children.Item("date").Text
    Set elem = elem.Children.Item("clearingOrg")
        Dim ec As String
        ec = elem.Children.Item("ec").Text
  'Get a collection of "curConv" elements
    Set elem = elem.Children.Item("curConv")
     
    Dim length As Integer
    length = elem.length - 1
    
    Dim obj As Object
    Dim fromCur As String
    Dim toCur As String
    Dim convRate As String

    Dim db As Database
    Set db = CurrentDb()
       
  'Delete data from database
    DoCmd.SetWarnings False
    Dim strsql As String
    strsql = "Delete * From curConv;"
    DoCmd.RunSQL strsql
    DoCmd.SetWarnings True
    
    Dim rs As Recordset
    Set rs = db.OpenRecordset("curConv", dbOpenDynaset)
    
    Dim retVal
    Dim i As Integer

  'For each "curconv" element add a new record to the table
    For i = 0 To length
        Set obj = elem.Item(i)
        fromCur = obj.Children.Item("fromCur").Text
        toCur = obj.Children.Item("toCur").Text
        convRate = obj.Children.Item("factor").Text
        retVal = utilFunc.addNewRecord(rs, busDate, ec, fromCur, toCur, convRate)
    Next i
    
    rs.Close
    Set db = Nothing
    DoCmd.OpenForm ("Currency Conversion Rates")
    
End Function

Function addNewRecord(rs As Recordset, _
    busDate As String, _
    ec As String, _
    fromCur As String, _
    toCur As String, _
    convRate As String)

    rs.AddNew                   ' Add new record.
    rs!busDate = busDate        ' Add data.
    rs!clearingOrg = ec
    rs!fromCurrency = fromCur
    rs!toCurrency = toCur
    rs!convRate = convRate
    rs.Update                   ' Save changes.

End Function