SAX for Pascal Home   SAX for Pascal Documentation

Choosing a Parser from a List

This demo is intended to show you how you can fill a list with all of the available parsers. In addition it shows the basics of checking the features of an XMLReader. This demo does not include any information about parsing. For more information about parsing, please see the Simple Parsing Demo.

Adding the parsers to the project

In order to fill the list with parsers you must first make sure that there are available parsers within your project. To do this, you must add the files to the Project. (The technical reasons behind this are simple, the initialization code for each parser package must be called. By adding the unit to the project you can be sure that the project will execute the code in the package's initialization section)

First click "Project | Add To Project" on the file menu. In this demo you should see that SAXKW and SAXMS have already been added for you. This allows you to use either of the default parsers provided by Keith Wood. You can add another parser by including the unit that declares that package's vendor information.

Filling the lists

Now that you have some available SAX parsers you will want to add some code to fill a list. In this demo our list is a TComboBox string list. We will need to include the SAX unit in the uses clause. Then we can just add the code to the FormCreate. First we fill the list, then we select the DefaultSAXVendor.

        // Fill the list
        ListSAXVendors(ComboBox1.Items);
        // Set the item index
        ComboBox1.ItemIndex:= ComboBox1.Items.IndexOf(DefaultSAXVendor);
      

Remember the DefaultSAXVendor is a SAXString so we must look it up by it's index in the ComboBox rather than simply setting the ItemIndex.

Getting information about each parser

Now that we have code to fill the list with the available parsers, we will add an OnChange event to the our TComboBox so that we can see the features of each parser's XMLReader. This demo shows which features are turned on by default. If a specific feature is not supported it will show "Not Supported". Checking certain features may not be supported at different times (e.g. when parsing or when not parsing) but may be supported at other times.

It is important to be aware that in SAX for Pascal there are two kinds of Vendors: Normal and Buffered. A Buffered Vendor is a vendor that is relying on the Buffered (or PSAXChar) versions of the interfaces, such as IBufferedXMLReader. Generally these parsers are much faster because they require fewer string allocations. A good example of a Buffered SAX vendor is KDSSAXExpat.

We begin by adding the event, then we will try to get information about the Vendor and XMLReader itself. Essentially we must begin by getting the Vendor and accessing the Description or XMLReader:

        // Get the vendor
        AVendor:= GetSAXVendor(ComboBox1.Items[ComboBox1.ItemIndex]);

        // Get the description
        labDesc.Caption:= AVendor.Description;

        // Get the XML Reader
        Buffered:= AVendor is TBufferedSAXVendor;
        if Buffered then
          AXMLReader:= TBufferedSAXVendor(AVendor).BufferedXMLReader
        else
          AXMLReader:= AVendor.XMLReader;
      

Again, we are checking what kind of Vendor we have. If it is a TBufferedXMLReader, we will access the BufferedXMLReader property. Once we have the XMLReader we can check its features. We must be careful however if a feature is not recognized the XMLReader will raise an ESAXNotRecognizedException. In some cases a checking property might not be supported when parsing or when not parsing. If checking a feature (or setting a feature) is not supported at a given time the XMLReader will raise an ESAXNotSupportedException exception. Because of this, it is safest to wrap this code in a try..except block:

        try
          // Check for the feature
          if GetFeature(ValidationFeature, AXMLReader, Buffered) then
            labVal.Caption:= 'Yes'
          else
            labVal.Caption:= 'No';
        except
          on e : ESAXNotRecognizedException do
          begin
            // The XMLReader didn't recognize the feature
            labVal.Caption:= 'Not recognized'
          end;
          on e2 : ESAXNotSupportedException do
          begin
            // The XMLReader doesn't support querying this feature right now
            labVal.Caption:= 'Not supported'
          end;
        end;
      

This will keep the exception from showing in the application. Instead it will only show when you are debugging the application in Delphi. You can also set features this way. Again, you need to be careful that the feature is recognized and supported.

Notice that we used the function GetFeature. You may be wondering what that function does. All it does is provide an easy way to check the feature of either a normal or Buffered XMLReader:

        function GetFeature(Feature: SAXString; XMLReader: IUnknown;
          Buffered: Boolean): Boolean;
        begin
          if Buffered then
            Result:= IBufferedXMLReader(XMLReader).Features[Feature]
          else
            Result:= IXMLReader(XMLReader).Features[Feature];
        end;
      

Features in SAX are identified by URLs. However, this does not mean that you can type a feature URL in the browser and look it up. They are simply used as unique identifiers. This demo shows all of the basic features but others may be used by specific vendors.