SAMPLE: SAX Win32 AppWizard Creates a Visual C++ SAX Application (276505)



The information in this article applies to:

  • Microsoft XML 3.0
  • Microsoft Visual C++, 32-bit Enterprise Edition 6.0
  • Microsoft Visual C++, 32-bit Professional Edition 6.0
  • Microsoft Visual C++, 32-bit Learning Edition 6.0

This article was previously published under Q276505

SUMMARY

Instead of using the Document Object Model (DOM), you can use the Simple API for XML (SAX) to provide a lower-level API to parse XML data that can result in a much greater performance gain under certain scenarios. For example, a messaging scenario where you preprocess and reroute XML documents to other servers.

SAX was originally defined as a set of Java APIs. The Microsoft XML parser (MSXML) version 3.0 maps the Java interfaces to COM interfaces, and in the July 2000 Web release, or in the later versions of our parser, SAX support is provided for programming with Microsoft Visual C++ and Microsoft Visual Basic. For related software development kit (SDK) documentation, see the following Microsoft Developer Network (MSDN) Web site: Together with the performance gain, programming in SAX can require some extra work from developers. To help programming in SAX with Visual C++, this article contains the SAX Win32 AppWizard, in addition to a sample program that was created by using this wizard.

Note As with other sample code, the SAX Win32 Appwizard is provided as an aid to developers; however, there is no support plan for this tool.

MORE INFORMATION

The following file is available for download from the Microsoft Download Center:
The SAXAppWizard.exe file contains the following files:

File nameSize
SAXAppWizard.awx116KB
a1.dsw1KB
a1.dsp2KB
a1.cpp5KB
a1ContentHandler.h2KB
a1ContentHandler.cpp3KB
SAXContentHandlerImpl.h3KB
SAXContentHandlerImpl.cpp4KB
StdAfx.h2KB
StdAfx.cpp1KB
Stock.xml1KB

How the SAX Interfaces Are Implemented in the AppWizard

Different approaches are available to implement a COM interface. The AppWizard uses the following statement to generate abstract class definitions for each SAX interface:
#import "msxml3.dll?" raw_interfaces_only
				
Note Although this is the correct way to generate all the wrapper classes to implement the COM interface, it is sometimes desirable to use the DOM interface with SAX, to trap all the COM errors as C++ exceptions, and to get all the benefits of _variant_t and _bstr_t. In that case, you can use the following combination instead:
#import <msxml3.dll> exclude("IErrorInfo") high_method_prefix("_") raw_method_prefix("")
				
Because you may be only interested in handling certain events that are defined by the interface, you do not have to implement all the methods in the interface. However, all the functions that are defined in the SAX interfaces (such as ISAXContentHandler) are pure virtual functions. To resolve this issue, the AppWizard generates a middle wrapper class (for example, SAXContentHandlerImpl) that extends the SAX interface and wraps all the functions.

Additionally, the three basic methods of the COM interface (QueryInterface, AddRef, and Release) are implemented in this class. After you decide which events you want to handle, a derived class from this wrapper class is generated based on your selection; this is the template class that you must modify to complete the implementation (for example, "class A1ContentHandler : public SAXContentHandlerImpl").

How to Use the SAX Win32 AppWizard

You will use the AppWizard to create a Visual C++ SAX application that prints XML content to a console window. The AppWizard automatically creates a Stock.xml file in your project folder, that you will use as the input XML data for your sample application.

To create a sample application, follow these steps:
  1. Copy the SAXAppWizard.awx file to the MSDev template folder. By default, this is located at C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Template.
  2. Start Visual C++, and create a new project. You see SAX Win32 AppWizard among the options. Select it, type the name of the project (such as "a1"), and then click Next.
  3. In the second dialog box, you decide which handlers and methods that you must have to implement. For simplicity, only implement the content handler to handle three events in this sample: startElement, characters, and endElement. Double-click (or use << or >>) to select or remove items. Click Finish to generate the project.
  4. After the project is generated, click the class view and you see that two classes are generated to implement the content handler. One is SAXContentHandlerImpl, a wrapper class of the IXMLSAXContentHandler interface. The three basic methods of COM interfaces (QueryInterface, AddRef, and Release) are implemented in this class which controls the life cycle of the object.
  5. You also see that another class, that is named a1ContentHandler, is generated with three methods (startElement, characters, and endElement) to handle the events that you want. Two additional methods are also generated: prt is a helper method for printing, and CreateInstance is used to create an instance of the a1ContentHandler.
  6. In class view, under Global, click the main function, and then check the steps of the SAX application:
    1. Create Reader.
    2. Create an instance of a1ContentHandler.
    3. Call the putContentHandler method to register it with the XML Reader.
    4. parseURL with the path of the XML, and start parsing.
To complete the implementation of the content handler, follow these steps:
  1. In class view, double-click startElement to go to the implementation section of this method. Check the input parameters: pwchLocalName is the element tag name, and pAttributes is the collection of the current element. Call getLength to get the number of attributes, and use it to iterate through the attribute collection and print it out. For example:
    prt(L"<%s", pwchLocalName, cchLocalName);
    int lAttr;
    pAttributes->getLength(&lAttr);
    for(int i=0; i<lAttr; i++)
    {
    	wchar_t * ln, * vl; int lnl, vll;
    	pAttributes->getQName(i,&ln,&lnl); 
    	prt(L" %s=", ln, lnl);
    	pAttributes->getValue(i,&vl,&vll);
    	prt(L"\"%s\"", vl, vll);
    }
    printf(">");
    					
  2. Double-click characters in class view, and then locate the code section. Print the value of each element. For example:
    prt(L"%s", pwchChars, cchChars);
    					
  3. Double-click endElement in class view, and then locate the code section. There is not much work to do in this method; only print the end tag. For example:
    prt(L"</%s>",pwchLocalName,cchLocalName);
    					
  4. Compile and run the application. If you run it inside the debugger, put Stock.xml as the input of the program argument (project settings). If everything is implemented correctly, you see the content of Stock.xml printed in the console window.

Modification Type:MinorLast Reviewed:8/5/2004
Keywords:kbdownload kbdownload kbfile kbhowto kbMSXMLnosweep KB276505 kbAudDeveloper