perfectxml.com
 Basic Search  Advanced Search   
Topics Resources Free Library Software XML News About Us
  You are here: home »» Info Bank »» Articles » MSXML with Internet Explorer 4.0 Sunday, 28 October 2007
 

Back to Articles Page      

        


MSXML with Internet Explorer 4.0


Table of contents
Introduction
MSXML 1.0 in Detail
Sample C++ Program
Sample JScript Program
Summary



  • Introduction
    Microsoft certainly did a good job with version 3.0 of their XML Parser (MSXML 3.0 External link ), with complete implementation of XSLT & XPath W3C specifications, improved SAX2, DOM and namespace support, Server-safe HTTP access, quite a few bug fixes and performance improvements. But what if the 'minimum requirements' for your product(s) specifies Internet Explorer 4.0 and you need to deal with XML Parsing? Don't go and tell your manager that you'll need 10 days more to write & test XML Parser yourself!

    Microsoft shipped MSXML 1.0 External link , a very basic, DOM-based, non-validating, high-performance XML Parser written in C++, with Internet Explorer 4.0. This early version of the parser is contained in the MSXML.dll library (file version 4.7x.xxxx.x). At the same time, Microsoft also shipped a Java version External link of validating XML Parser, however, is deprecated and has not been updated.

    In this article, we'll learn how to use MSXML 1.0 so that your application can work with Internet Explorer 4.0. We'll write a sample C++ program to load and parse an XML document and we'll do the same thing using a JScript program also.


  • MSXML 1.0 in Detail
    The MSXML 1.0 library with ProgID "MSXML" has just four interfaces: IXMLDocument, IXMLElement, IXMLElementCollection, and IXMLError.

    The first step is to create an IXMLDocument object using "MSXML" as ProgID. Next, to load an XML document, just update the URL property or call put_URL method if you are programming in C++. The document is loaded synchronously. Note that with this version of MSXML, you cannot load XML documents using a string; only loading from URI is supported. IXMLDocument loads the XML document and initializes it's properties like filesize, charset, version, doctype, dtdURL, and mimeType.

    The XML document is loaded as a tree, with root node of type IXMLElement. The get_root method returns the root node as IXMLElement object. The root node has a special importance, because all child nodes are accessed using this root node. To access children of root (or any other node/element), use children property (get_children method in C++), which returns an IXMLElementCollection object. The other members of IXMLElement interface allow to add/remove children, get/set tag name, and get/set tag value, get/set element attributes. The access to attributes as enumeration was introduced in MSXML 1.0 file that shipped with SP1 for Internet Explorer 4.0.

    The only two important members for IXMLElementCollection interface are length and item. Using item method you can retrieve child elements using index, name or both.

    To summarize, create IXMLDocument object, update it's URL property, get document's root node, after that it's just children (IXMLElementCollection) and item (IXMLElement).



  • Sample C++ Program
    Let's now take a look at a C++ program that uses MSXML 1.0 to load and parse an XML document. But first, our sample XML document:

    <?xml version="1.0" ?>

    <BankAccount>

          <Number>1234</Number>

          <Name>Darshan Singh</Name>

          <Type>Checking</Type>

          <OpenDate>11/04/1974</OpenDate>

          <Balance>25382.20</Balance>

    </BankAccount>


    Let's save above XML document as c:\1.xml.

    Steps to create sample C++ Program:
    Step 1. Create a Win32 Console application and select "A simple application" from the next screen.

    Step 2. Write the following lines immediately below #include "stdafx.h" and above main():

    #include <atlbase.h>

    enum ISztagXMLEMEM_TYPE

    {

        ISzXMLELEMTYPE_ELEMENT,

        ISzXMLELEMTYPE_TEXT,

        ISzXMLELEMTYPE_COMMENT,

        ISzXMLELEMTYPE_DOCUMENT,

        ISzXMLELEMTYPE_DTD,

        ISzXMLELEMTYPE_PI,

        ISzXMLELEMTYPE_OTHER

    };

     

    const BSTR pszXMLDLL = L"msxml";

    const BSTR szURL = L"c:\\1.xml";

     

    struct __declspec(uuid("F52E2B61-18A1-11d1-B105-00805F49916B")) IXMLDocument;

    struct __declspec(uuid("3F7F31AC-E15F-11d0-9C25-00C04FC99C8E")) IXMLElement;

    struct __declspec(uuid("65725580-9B5D-11d0-9BFE-00C04FC99C8E")) IXMLElementCollection;

     

    HRESULT TraverseNode ( IXMLElement* pElement, CComBSTR & bstrXML );



    The above lines include atlbase.h, declare element type enumeration, declare ProgID, XML document location, interface declaration with their IIDs, and a recursive function used in this sample program.

    Step 3: Next, we'll write the code for our main function:

    int main(int argc, char* argv[])

    {

                    CLSID CLSID_IXMLDocument;

                    CComPtr  <IXMLDocument>    spXMLDoc;

                    CComPtr  <IXMLElement>        spRootElement;

     

                    CoInitialize(NULL);

     

                    HRESULT hr = CLSIDFromProgID( pszXMLDLL, &CLSID_IXMLDocument );

     

                    if ( SUCCEEDED ( hr ) )

                    {

                                    hr = ::CoCreateInstance( CLSID_IXMLDocument, NULL, CLSCTX_INPROC_SERVER,                                                                                           IID_IXMLDocument, (void**)&spXMLDoc );

                                    if (SUCCEEDED(hr))

                                    {

                                                    hr = spXMLDoc->put_URL( szURL );

                                                    if ( ( SUCCEEDED ( hr ) ) && ( spXMLDoc.p ) )

                                                    {

                                                                    hr = spXMLDoc->get_root( &spRootElement );

                                                                    CComBSTR bstrXML;

     

                                                                    hr = TraverseNode(spRootElement, bstrXML);

     

                                                                    USES_CONVERSION:

                                                                    printf(W2A(bstrXML));

                                                    }

                                    }

                    }

                   

                    return 0;

    }



    The above code simply creates MSXML IXMLDocument object objects, loads the document using put_URL method, gets root node using get_root method and finally calls TraverseNode which recursively scans the XML document and generates the string which represent the loaded XML document. Finally, we print the generated XML string, which is actually original XML document fragment: <BANKACCOUNT><NUMBER>1234</NUMBER><NAME>Darshan Singh</NAME> <TYPE>Checking</TYPE><OPENDATE>11/04/1974</OPENDATE><BALANCE>25382.20</BALANCE></BANKACCOUNT>

    Step 4: Finally, let's now look at the recursive function, which does the actual job of stepping through the XML document tree:

    HRESULT TraverseNode ( IXMLElement* pElement, CComBSTR & bstrXML )

    {

                    HRESULT hr = S_OK;

                    long lElemType;

     

                    hr = pElement->get_type( &lElemType );

                    if ( SUCCEEDED ( hr ) && ISzXMLELEMTYPE_ELEMENT == lElemType ) //=0

                    {

                                    CComBSTR bstTagName;

                                    hr = pElement->get_tagName( &bstTagName );

                                   

                                    if ( SUCCEEDED ( hr ) )

                                    {

                                                    bstrXML += "<";

                                                    bstrXML += bstTagName;

                                                    bstrXML += ">";

     

                                                    IXMLElementCollection* pChildrenColl;

                                                    pElement->get_children( &pChildrenColl );

     

                                                    long lNoOfChildrens;

                                                    hr = pChildrenColl->get_length( &lNoOfChildrens );

     

                                                    VARIANT vIndex;

                                                    vIndex.vt                 = VT_I4;

                                                    VARIANT vName;

                                                    vName.vt                 = VT_ERROR;

                                                    vName.scode          = DISP_E_PARAMNOTFOUND;               

                                                    if( SUCCEEDED ( hr ) && lNoOfChildrens > 0 )

                                                    {

                                                                    int iIndex = 0;

                                                                    for ( iIndex  = 0; iIndex < lNoOfChildrens; iIndex++ )

                                                                    {

                                                                                    IXMLElement* pChildElement;

                                                                                   

                                                                                    vIndex.intVal = iIndex;

                                                                                   

                                                                                    hr = pChildrenColl->item( vIndex, vName,                                                                                                                               (IDispatch**)&pChildElement );

                                                                                   

                                                                                    if( SUCCEEDED ( hr ) )

                                                                                    {

                                                                                                    hr = TraverseNode ( pChildElement, bstrXML );

                                                                                    }

                                                                    }

     

                                                    }

                                                    bstrXML += "</";

                                                    bstrXML += bstTagName;

                                                    bstrXML += ">";

                                    }

     

                    }

                    else

                    {

                                    if ( ISzXMLELEMTYPE_TEXT == lElemType ) //=1

                                    {

                                                    BSTR bstrChildText;

                                                    hr = pElement->get_text( &bstrChildText );

                                                    if( SUCCEEDED ( hr ) )

                                                    {

                                                                    bstrXML += bstrChildText;

                                                    }

                                    }

                    }

     

                    return hr;

    }



    The above recursive function, starts with checking the type of the element, if it's an element node, we just get the tag name, add the tag name to output string, get this element node's children and for each child call the method again recursively. But if the current node is of type text (without any sub-elements), we get the text property and again append it to output string.


  • Sample JScript Program
    Let's now do the same thing using a JScript program.

    <script language="JScript" for="window" event="onload">

                    var objDoc = new ActiveXObject("msxml");

                    objDoc.URL = "c:\\1.xml";

     

                    var objRoot = objDoc.root;

                    var strOutput = " ";

                    TraverseNode (objRoot);

                    alert (strOutput);

     

                    function TraverseNode (objCurElem)

                    {

                                    var iIndex, iCount;

                                    if (objCurElem.type == 0)

                                    {

                                                    strOutput = strOutput + "<" + objCurElem.tagName + ">" ;

                                                    if (objCurElem.children != null)

                                                    {

                                                                    iCount = objCurElem.children.length;

                                                                    for (iIndex =0; iIndex < iCount; iIndex ++)

                                                                                    TraverseNode(objCurElem.children.item(iIndex));

                                                    }

                                                    strOutput = strOutput + "</" + objCurElem.tagName + ">" ;

                                    }

                                    else

                                    {

                                                    if (objCurElem.type == 1)

                                                                    strOutput = strOutput +  objCurElem.text ;

                                    }

                    }

    </script>

     



  • Summary
    In this article, we looked at how to use MSXML 1.0 parser, that shipped with Intenet Explorer 4.0, with the help of a C++ and JScript sample program. If you have any questions/comments, please feel free to contact author, Darshan Singh, at .


  

Back to Articles Page      

All information on this site is for training only. We do not warrant its correctness or its fitness to be used. The risk of using it remains entirely with the user.

 

  Contact Us |  | Site Guide | About PerfectXML | Advertise ©2004 perfectxml.com. All rights reserved. | Privacy