#include #include #include template class __declspec(novtable) StackUnknown : public Base { public: virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void ** ppv); virtual ULONG STDMETHODCALLTYPE AddRef() {return 1;} virtual ULONG STDMETHODCALLTYPE Release() {return 1;} }; template HRESULT STDMETHODCALLTYPE StackUnknown::QueryInterface(REFIID riid, void ** ppv) { if (riid == __uuidof(Base) || riid == __uuidof(IUnknown)) { // // No need to AddRef since this class // will only be created on the stack // *ppv = this; return S_OK; } *ppv = NULL; return E_NOINTERFACE; } class FileOutputStream : public StackUnknown { public: FileOutputStream() {_fClose = false;} ~FileOutputStream() {Close();} HRESULT Init(HANDLE h) { _h = h; _fClose = false; return S_OK;} HRESULT Init(const WCHAR * pwszFileName); void Close() {if (_fClose) {::CloseHandle(_h); _fClose = false;} } virtual HRESULT STDMETHODCALLTYPE Read(void * pv, ULONG cb, ULONG * pcbRead) {return E_NOTIMPL;} virtual HRESULT STDMETHODCALLTYPE Write(void const * pv, ULONG cb, ULONG * pcbWritten); private: HANDLE _h; bool _fClose; }; HRESULT FileOutputStream::Init(const WCHAR * pwszFileName) { HRESULT hr = S_OK; _h =::CreateFileW( pwszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if( INVALID_HANDLE_VALUE != _h ){ hr = HRESULT_FROM_WIN32( GetLastError() ); } _fClose = true; return hr; } HRESULT STDMETHODCALLTYPE FileOutputStream::Write(void const * pv, ULONG cb, ULONG * pcbWritten) { HRESULT hr = S_OK; BOOL bResult; bResult = ::WriteFile( _h, pv, cb, pcbWritten, NULL); if( !bResult ){ hr = HRESULT_FROM_WIN32( GetLastError() ); } return hr; } extern "C" { HRESULT TransformXML( LPWSTR szXML, LPWSTR szXSL, LPWSTR szResult ) { HRESULT hr; IXMLDOMDocument* pXMLDoc = NULL; IXMLDOMDocument* pXSLDoc = NULL; IXSLTemplate* pTemplate = NULL; IXSLProcessor * pProcessor = NULL; FileOutputStream OutputStream; BSTR bszResult = NULL; VARIANT_BOOL vStatus; VARIANT vXML; VARIANT vXSL; VARIANT vDoc; VariantInit( &vXML ); VariantInit( &vXSL ); hr = OutputStream.Init(szResult); if(FAILED(hr)){ goto cleanup; } vXML.vt = VT_BSTR; vXML.bstrVal = SysAllocString( szXML ); vXSL.vt = VT_BSTR; vXSL.bstrVal = SysAllocString( szXSL ); hr = CoInitialize(0); hr = CoCreateInstance( CLSID_FreeThreadedDOMDocument, NULL, CLSCTX_SERVER, IID_IXMLDOMDocument, (void**)&pXMLDoc ); if(FAILED(hr)){ goto cleanup; } hr = CoCreateInstance( CLSID_FreeThreadedDOMDocument, NULL, CLSCTX_SERVER, IID_IXMLDOMDocument, (void**)&pXSLDoc ); if(FAILED(hr)){ goto cleanup; } hr = CoCreateInstance( CLSID_XSLTemplate, NULL, CLSCTX_SERVER, IID_IXSLTemplate, (void**)&pTemplate ); if(FAILED(hr)){ goto cleanup; } hr = pXMLDoc->put_preserveWhiteSpace(VARIANT_TRUE); hr = pXMLDoc->put_async(VARIANT_FALSE); hr = pXMLDoc->load( vXML, &vStatus ); if(FAILED(hr) || vStatus == false ){ goto cleanup; } hr = pXSLDoc->put_preserveWhiteSpace(VARIANT_TRUE); hr = pXSLDoc->put_async(VARIANT_FALSE); hr = pXSLDoc->load( vXSL, &vStatus ); if(FAILED(hr) || vStatus == false ){ goto cleanup; } hr = pTemplate->putref_stylesheet(pXSLDoc); vDoc.vt = VT_UNKNOWN; vDoc.punkVal = (IUnknown*)pXMLDoc; pTemplate->createProcessor(&pProcessor); hr = pProcessor->put_input( vDoc ); vDoc.punkVal = &OutputStream; hr = pProcessor->put_output( vDoc ); hr = pProcessor->transform( &vStatus ); cleanup: if( NULL != pTemplate ){ pTemplate->Release(); } if( NULL != pProcessor ){ pProcessor->Release(); } if( NULL != pXMLDoc ){ pXMLDoc->Release(); } if( NULL != pXSLDoc ){ pXSLDoc->Release(); } VariantClear( &vXML ); VariantClear( &vXSL ); return hr; } } //extern C