MSXSL C++ compiled stylesheet code

Subject: MSXSL C++ compiled stylesheet code
From: Andrew Kimball <akimball@xxxxxxxxxxxxx>
Date: Wed, 4 Oct 2000 16:20:01 -0700
Below is some MSXSL C++ compiled stylesheet code that several people have
asked me to post.  I haven't thoroughly tested it, so don't fully trust it :
).  Also, as soon as I can get it done, I plan to post a simple shell
executable on the MS XML site that will perform command-line transformations
(by invoking the MSXML DLL).  All of the code for the executable (including
this excerpt) will probably be available as a sample of how to use the MSXML
COM objects.

~Andy Kimball
MSXSL Dev


HRESULT
TransformHelper::LoadDOM(IXMLDOMDocument * pDOM, BSTR bstrFileName)
{
    HRESULT hr = S_OK;
    VARIANT vFileName;
    VARIANT_BOOL fSuccess;

    V_VT(&vFileName) = VT_BSTR;
    V_BSTR(&vFileName) = bstrFileName;

    ChkSucc(pDOM->put_async(VARIANT_FALSE));
    ChkSucc(pDOM->load(vFileName, &fSuccess));
    if (fSuccess == VARIANT_FALSE)
    {
        hr = E_FAIL;
    }

Cleanup:
    return hr;
}

HRESULT
TransformHelper::Transform()
{
    HRESULT hr = S_OK;
    LARGE_INTEGER start = {0, 0};
    ULARGE_INTEGER cb;
    IXMLDOMDocument * pInput = NULL;
    IXMLDOMDocument * pStylesheet = NULL;
    IXSLTemplate * pTemplate = NULL;
    IXSLProcessor * pProcessor = NULL;
    VARIANT vOut, vInput;
    VARIANT_BOOL fDone;
    BYTE * pbOutput = NULL;

    Assert(_bstrInput && _bstrStylesheet && _bstrOutput);

    // Initialized in-memory stream (faster than writing to a BSTR)
    if (!_pIStream)
    {
        ChkSucc(CreateStreamOnHGlobal(0, TRUE, &_pIStream));
        ChkSucc(::GetHGlobalFromStream(_pIStream, &_hOutput));
    }
    else
    {
        // Seek to beginning of stream (reset it)
        ChkSucc(_pIStream->Seek(start, STREAM_SEEK_SET, NULL));
    }

    ChkSucc(::CoCreateInstance(
                CLSID_FreeThreadedDOMDocument,
                NULL,
                CLSCTX_SERVER,
                IID_IXMLDOMDocument,
                (void **) &pStylesheet));

    // Load stylesheet document
    ChkSucc(LoadDOM(pStylesheet, _bstrStylesheet));

    ChkSucc(::CoCreateInstance(
                CLSID_DOMDocument,
                NULL,
                CLSCTX_SERVER,
                IID_IXMLDOMDocument,
                (void **) &pInput));

    // Load source document
    ChkSucc(LoadDOM(pInput, _bstrInput));

    ChkSucc(::CoCreateInstance(
                CLSID_XSLTemplate,
                NULL, 
                CLSCTX_SERVER,
                IID_IXSLTemplate,
                (void **) &pTemplate));

    // Compile stylesheet
    ChkSucc(pTemplate->putref_stylesheet(pStylesheet));

    // createProcessor can be concurrently called on multiple threads (i.e.
in a server environment), allowing multiple threads
    // to transform different XML files, using different parameters, while
using the same stylesheet.  While the XSLTemplate
    // is thread-safe in order to enable this scenario, each XSLProcessor
must be used on only one thread at a time.
    ChkSucc(pTemplate->createProcessor(&pProcessor));

    // Provide the source document to the XSLProcessor
    V_VT(&vInput) = VT_UNKNOWN;
    V_UNKNOWN(&vInput) = (IUnknown *) pInput;
    ChkSucc(pProcessor->put_input(vInput));

    // Provide the output stream to the XSLProcessor
    V_VT(&vOut) = VT_UNKNOWN;
    V_UNKNOWN(&vOut) = (IUnknown *) _pIStream;
    ChkSucc(pProcessor->put_output(vOut));

    // Execute stylesheet
    ChkSucc(pProcessor->transform(&fDone));

    // Get number of bytes written to output stream (unless you may output
more than 4 GB, cb.LowPart has the total #bytes)
    ChkSucc(_pIStream->Seek(start, STREAM_SEEK_CUR, &cb));

    // Get pointer to stream's memory
    pbOutput = (BYTE *) ::GlobalLock(_hOutput);

    // ==== Insert code here to output to a file, etc. using  pbOutput & cb
====

Cleanup:
     if (pbOutput)
        ::GlobalUnlock(_hOutput);

    SafeRelease(pInput);
    SafeRelease(pStylesheet);
    SafeRelease(pProcessor);
    SafeRelease(pTemplate);

    return hr;
}


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread