Share via


Source: XSLT.cpp

 

The source code listed below demonstrates how to call the transformNode method and the transformNodeToObject method in a C/C++ program. Specifically, the code performs the following steps:

  1. Loads the XML data file (stocks.xml) into an XML DOM object (pXMLDom).

  2. Loads the XSLT style sheet (stocks.xsl) into an XML DOM object (pXSLDoc).

  3. Calls the transformNode(pXSLDoc) method on pXMLDom to do the transformation, holds the result in a string, and prints the output to the console.

  4. Creates an XML DOM object (pXMLOut) to hold the output of the transformNodeToObject method.

  5. Calls the transformNodeToObject method on pXMLDom to do the transformation; holds the resulting object in pXMLOut; prints out the XML result; and serializes the output object in an HTML file, stocks.htm.

To add XSLT.cpp to the project

  1. Create a new C++ source file. For detailed instructions on how to do this, see Set Up My Visual C++ Project. Name the new file XSLT.cpp.

  2. Copy the C/C++ source code above and paste it into the source file you just created.

  3. Next, we'll add the resource files to the XSLT project.

C/C++ Source File (XSLT.cpp)

// XSLT.cpp : Defines the entry point for the console application.
//

#include <stdio.h>
#include <tchar.h>
#include <msxml6.h>

// Macro that calls a COM method returning HRESULT value.
#define CHK_HR(stmt)        do { hr=(stmt); if (FAILED(hr)) goto CleanUp; } while(0)

// Macro to verify memory allcation.
#define CHK_ALLOC(p)        do { if (!(p)) { hr = E_OUTOFMEMORY; goto CleanUp; } } while(0)

// Macro that releases a COM object if not NULL.
#define SAFE_RELEASE(p)     do { if ((p)) { (p)->Release(); (p) = NULL; } } while(0)

// Helper function to create a VT_BSTR variant from a null terminated string. 
HRESULT VariantFromString(PCWSTR wszValue, VARIANT &Variant)
{
    HRESULT hr = S_OK;
    BSTR bstrString = SysAllocString(wszValue);
    CHK_ALLOC(bstrString);
    
    V_VT(&Variant)   = VT_BSTR;
    V_BSTR(&Variant) = bstrString;

CleanUp:
    return hr;
}

// Helper function to create a DOM instance. 
HRESULT CreateAndInitDOM(IXMLDOMDocument **ppDoc)
{
    HRESULT hr = CoCreateInstance(__uuidof(DOMDocument60), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(ppDoc));
    if (SUCCEEDED(hr))
    {
        // these methods should not fail so don't inspect result
        (*ppDoc)->put_async(VARIANT_FALSE);  
        (*ppDoc)->put_validateOnParse(VARIANT_FALSE);
        (*ppDoc)->put_resolveExternals(VARIANT_FALSE);
    }
    return hr;
}

// Helper function to load xml from file. 
HRESULT LoadXMLFile(IXMLDOMDocument *pXMLDom, LPCWSTR lpszXMLFile)
{
    HRESULT hr = S_OK;
    VARIANT_BOOL varStatus;
    VARIANT varFileName;
    IXMLDOMParseError *pXMLErr=NULL;
    BSTR bstrErr = NULL;

    VariantInit(&varFileName);
    CHK_HR(VariantFromString(lpszXMLFile, varFileName));
    CHK_HR(pXMLDom->load(varFileName, &varStatus));

    //load xml failed
    if(varStatus != VARIANT_TRUE)
    {
        hr = E_FAIL;
        CHK_HR(pXMLDom->get_parseError(&pXMLErr));
        CHK_HR(pXMLErr->get_reason(&bstrErr));
        printf("Failed to load %S:\n%S\n", lpszXMLFile, bstrErr);
    }

CleanUp:
    SAFE_RELEASE(pXMLErr);
    SysFreeString(bstrErr);
    VariantClear(&varFileName);
    return hr;
}

// Helper function to transform DOM to a string. 
HRESULT TransformDOM2Str(IXMLDOMDocument *pXMLDom, IXMLDOMDocument *pXSLDoc)
{
    HRESULT hr = S_OK;
    BSTR bstrResult = NULL;
    CHK_HR(pXMLDom->transformNode(pXSLDoc, &bstrResult));
    printf("Output from transformNode:\n%S\n", bstrResult);

CleanUp:
    SysFreeString(bstrResult);
    return hr;
}

// Helper function to transform DOM to an object. 
HRESULT TransformDOM2Obj(IXMLDOMDocument *pXMLDom, IXMLDOMDocument *pXSLDoc)
{
    HRESULT hr = S_OK;
    BSTR bstrXML = NULL;
    IXMLDOMDocument *pXMLOut = NULL;
    IDispatch *pDisp = NULL;
    VARIANT varDisp;
    VARIANT varFileName;

    VariantInit(&varDisp);
    VariantInit(&varFileName);
    
    CHK_HR(CreateAndInitDOM(&pXMLOut));
    CHK_HR(pXMLOut->QueryInterface(IID_IDispatch, (void**)&pDisp));

    V_VT(&varDisp) = VT_DISPATCH;
    V_DISPATCH(&varDisp) = pDisp;
    pDisp = NULL;

    CHK_HR(pXMLDom->transformNodeToObject(pXSLDoc, varDisp));
    CHK_HR(pXMLOut->get_xml(&bstrXML));
    printf("Output from transformNodeToObject:\n%S\n", bstrXML);
    
    //save to stocks.htm
    CHK_HR(VariantFromString(L"stocks.htm", varFileName));
    CHK_HR(pXMLOut->save(varFileName));
    printf("The above output is also saved in stocks.htm.\n");

CleanUp:
    VariantClear(&varDisp);
    VariantClear(&varFileName);
    SysFreeString(bstrXML);
    SAFE_RELEASE(pXMLOut);
    return hr;
}

void XSLT()
{
    HRESULT hr = S_OK;
    IXMLDOMDocument *pXMLDom=NULL;
    IXMLDOMDocument *pXSLDoc=NULL;

    CHK_HR(CreateAndInitDOM(&pXMLDom));
    CHK_HR(LoadXMLFile(pXMLDom, L"stocks.xml"));
    CHK_HR(CreateAndInitDOM(&pXSLDoc));
    CHK_HR(LoadXMLFile(pXSLDoc, L"stocks.xsl"));

    // Transform dom to a string:
    CHK_HR(TransformDOM2Str(pXMLDom, pXSLDoc));
    // Transform dom to another dom object:
    CHK_HR(TransformDOM2Obj(pXMLDom, pXSLDoc));

CleanUp:
    SAFE_RELEASE(pXSLDoc);
    SAFE_RELEASE(pXMLDom);
}

int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT hr = CoInitialize(NULL);
    if(SUCCEEDED(hr))
    {
        XSLT();
        CoUninitialize();
    }

    return 0;

}