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.
C/C++ Source File (XSLT.cpp)
#include <stdio.h> #include <windows.h> #import <msxml5.dll> raw_interfaces_only using namespace MSXML2; // Macro that calls a COM method returning HRESULT value: #define HRCALL(a, errmsg) \ do { \ hr = (a); \ if (FAILED(hr)) { \ dprintf( "%s:%d HRCALL Failed: %s\n 0x%.8x = %s\n", \ __FILE__, __LINE__, errmsg, hr, #a ); \ goto clean; \ } \ } while (0) // Helper function that puts output in stdout and debug window // in Visual Studio: void dprintf( char * format, ...) { static char buf[1024]; va_list args; va_start( args, format ); vsprintf( buf, format, args ); va_end( args); OutputDebugStringA( buf); printf("%s", buf); } // Helper function to create a DOM instance: IXMLDOMDocument * DomFromCOM() { HRESULT hr; IXMLDOMDocument *pxmldoc = NULL; HRCALL( CoCreateInstance(__uuidof(DOMDocument50), NULL, CLSCTX_INPROC_SERVER, __uuidof(IXMLDOMDocument), (void**)&pxmldoc), "Create a new DOMDocument"); HRCALL( pxmldoc->put_async(VARIANT_FALSE), "should never fail"); HRCALL( pxmldoc->put_validateOnParse(VARIANT_FALSE), "should never fail"); HRCALL( pxmldoc->put_resolveExternals(VARIANT_FALSE), "should never fail"); return pxmldoc; clean: if (pxmldoc) { pxmldoc->Release(); } return NULL; } int main(int argc, char* argv[]) { IXMLDOMDocument *pXMLDom=NULL; IXMLDOMDocument *pXSLDoc=NULL; IXMLDOMParseError *pXMLErr=NULL; IXMLDOMDocument *pXMLOut = NULL; IDispatch *pDisp=NULL; BSTR bstr = NULL; long ecode; VARIANT_BOOL status; VARIANT var; HRESULT hr; CoInitialize(NULL); pXMLDom = DomFromCOM(); if (!pXMLDom) goto clean; VariantInit(&var); V_BSTR(&var) = SysAllocString(L"stocks.xml"); V_VT(&var) = VT_BSTR; HRCALL(pXMLDom->load(var,&status),"dom->load(): "); if (status!=VARIANT_TRUE) { HRCALL(pXMLDom->get_parseError(&pXMLErr), "dom->get_parseError: "); HRCALL(pXMLErr->get_reason(&bstr), "parseError->get_reason: "); dprintf("Failed to load DOM from stocks.xml. %S\n", bstr); goto clean; } pXSLDoc = DomFromCOM(); if (!pXSLDoc) goto clean; VariantClear(&var); V_BSTR(&var) = SysAllocString(L"stocks.xsl"); V_VT(&var) = VT_BSTR; HRCALL(pXSLDoc->load(var,&status), "xsl->load(): "); if (status != VARIANT_TRUE) { HRCALL(pXMLDom->get_parseError(&pXMLErr), "dom->get_parseError: "); HRCALL(pXMLErr->get_reason(&bstr), "parseError->get_reason: "); dprintf("Failed to load DOM from stocks.xsl. %S\n", bstr); goto clean; } // Transform dom to a string: HRCALL(pXMLDom->transformNode(pXSLDoc, &bstr),""); HRCALL(pXMLDom->get_parseError(&pXMLErr), ""); HRCALL(pXMLErr->get_errorCode(&ecode), ""); if (ecode != 0) { if (bstr) SysFreeString(bstr); HRCALL(pXMLErr->get_reason(&bstr),""); dprintf("Failed to transformNode:\n%S\n", bstr); goto clean; } dprintf("output from transformNode:\n%S\n",bstr); // Transform dom to another dom object: pXMLOut = DomFromCOM(); if (!pXMLOut) goto clean; HRCALL(pXMLOut->QueryInterface(IID_IDispatch,(void**)&pDisp), "QI(IDispatch): "); VariantClear(&var); var.vt = VT_DISPATCH; var.pdispVal = pDisp; HRCALL(pXMLDom->transformNodeToObject(pXSLDoc, var), "tramsformNodeToObject: "); if (bstr) SysFreeString(bstr); HRCALL(pXMLOut->get_xml(&bstr), ""); dprintf("output from transformNodeToObject:\n%S\n",bstr); VariantClear(&var); pDisp=NULL; V_VT(&var) = VT_BSTR; V_BSTR(&var) = SysAllocString(L"stocks.htm"); HRCALL(pXMLOut->save(var), "XMLOut->save: "); dprintf("The above output is also saved in stocks.htm.\n"); clean: if (bstr) SysFreeString(bstr); if (&var) VariantClear(&var); if (pXMLErr) { pXMLErr->Release();} if (pXMLDom) { pXMLDom->Release();} if (pXMLOut) { pXMLOut->Release();} if (pXSLDoc) { pXSLDoc->Release();} CoUninitialize(); return 0; }
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.