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:
Loads the XML data file (stocks.xml) into an XML DOM object (
pXMLDom
).Loads the XSLT style sheet (stocks.xsl) into an XML DOM object (
pXSLDoc
).Calls the
transformNode(pXSLDoc)
method onpXMLDom
to do the transformation, holds the result in a string, and prints the output to the console.Creates an XML DOM object (
pXMLOut
) to hold the output of thetransformNodeToObject
method.Calls the
transformNodeToObject
method onpXMLDom
to do the transformation; holds the resulting object inpXMLOut
; prints out the XML result; and serializes the output object in an HTML file, stocks.htm.
To add XSLT.cpp to the project
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.
Copy the C/C++ source code above and paste it into the source file you just created.
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;
}