This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
MSXSL C++ compiled stylesheet code
- To: "'xsl-list at mulberrytech dot com'" <xsl-list at mulberrytech dot com>
- Subject: MSXSL C++ compiled stylesheet code
- From: Andrew Kimball <akimball at microsoft dot com>
- Date: Wed, 4 Oct 2000 16:20:01 -0700
- Reply-To: xsl-list at mulberrytech dot com
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