Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ex-xslt2.cpp
#if defined(_WIN32)
# define WIN32_LEAN_AND_MEAN 1
# include <windows.h>
# define DLLHANDLE HMODULE
# define LOADERLIB "p6loader.dll"
# define LOADLIB(fn) LoadLibraryA((fn))
# define LOADSYMBOL(h,s) GetProcAddress((HMODULE)(h),(s))
# define FREELIB(h) FreeLibrary((HMODULE)(h))
#else
# include <errno.h>
# include <dlfcn.h>
# define DLLHANDLE void*
# define LOADERLIB "libp6loader.so"
# define LOADLIB(fn) dlopen((fn),RTLD_NOW)
# define LOADSYMBOL(h,s) dlsym((h),(s))
# define FREELIB(h) !dlclose((h))
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory> // nothrow
#include "filestream.h"
#include "p6xjr.h"
using namespace P6R;
P6DECLARE_CID( p6XSLT );
class CConsoleStream : public P6R::p6IDataStream
{
public:
P6COMMETHOD queryInterface( const P6REFIID iid, P6R::P6VOID **ppIface )
{
if (!ppIface) return eAccessFault;
*ppIface = NULL;
if(iid == IID_p6ICom) *ppIface = static_cast<p6IDataStream*>(this);
else if(iid == IID_p6IDataStream) *ppIface = static_cast<p6IDataStream*>(this);
else return eNoInterface;
reinterpret_cast<p6ICom*>(*ppIface)->addref();
return eOk;
}
{
return m_cRef++;
}
{
P6INT32 tmp = 0;
if(0 == (tmp = (--m_cRef))) { delete this; }
return tmp;
}
P6COMMETHOD beginStream()
{
return eOk;
}
P6COMMETHOD processStream( const P6R::P6VOID* pData, P6R::P6UINT32 cData )
{
if (m_cBuffer && cData+1 > m_cBuffer)
{
free( m_pBuffer );
m_pBuffer = NULL;
m_cBuffer = 0;
}
if (!m_pBuffer)
{
m_pBuffer = (P6CHAR*) malloc(cData+1);
m_cBuffer = cData;
}
if (m_pBuffer)
{
memcpy( m_pBuffer, pData, cData+1 );
m_pBuffer[cData] = '\0';
printf( m_pBuffer );
}
return eOk;
}
P6COMMETHOD endStream() { return eOk; }
static P6R::P6ERR createInstance( P6R::p6ICom *pOuter, const P6REFIID iid, P6R::P6VOID **ppIface )
{
P6ERR err = eNoMemory;
CConsoleStream *pObj = NULL;
if (NULL != (pObj = new (std::nothrow) CConsoleStream() ))
{
if (P6FAILED(err = pObj->queryInterface( iid, ppIface ))) delete pObj;
}
return err;
}
CConsoleStream() : m_cRef(0), m_pBuffer(NULL), m_cBuffer(0) {;}
virtual ~CConsoleStream() { if (m_pBuffer) free(m_pBuffer); }
protected:
P6INT32 m_cRef;
P6CHAR *m_pBuffer;
P6UINT32 m_cBuffer;
};
// Here is an example of both using JSON as the XSLT source document and
// outputing the template result tree as JSON.
//
static P6R::P6ERR runXSLT( p6IDataStream *pStream )
{
P6CHAR szErr[64];
CFileStream *pObj = NULL;
p6IDataStream* pOutStream1 = NULL;
p6IDataStream* pOutStream2 = NULL;
P6UINT32 bufSize = 0;
P6ERR err = eOk;
// Notice the output method is JSON in both templates
const P6CHAR* pTemplate1 =
"<?xml version='1.0' encoding='ISO-8859-1'?>\n" \
"<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>\n" \
"<xsl:output method='json'/>\n" \
" \n" \
"<xsl:variable name='gtlist' select='/staff/employee/name'/>\n" \
" \n" \
"<xsl:template match='/'>\n" \
"{{\"employee\":\n" \
"<xsl:text> [</xsl:text>" \
"<xsl:for-each select='$gtlist' >\n" \
" <xsl:sort select='.' />" \
"\"<xsl:value-of select='.' />\"" \
"<xsl:if test='position() != last()'>,\n </xsl:if>" \
"</xsl:for-each>\n" \
"<xsl:text>]\n}}</xsl:text>" \
"</xsl:template></xsl:stylesheet>";
const P6CHAR* pTemplate2 =
"<?xml version='1.0' encoding='ISO-8859-1'?>\n" \
"<xsl:stylesheet version='2.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>\n" \
"<xsl:output method='json'/>\n" \
" \n" \
"<xsl:variable name='gtlist' select='/JSON-document/staff/employee/name'/>\n" \
" \n" \
"<xsl:template match='/'>\n" \
"{{\"employee\":\n" \
"<xsl:text> [</xsl:text>" \
"<xsl:for-each select='$gtlist' >\n" \
" <xsl:sort select='.' />" \
"\"<xsl:value-of select='.' />\"" \
"<xsl:if test='position() != last()'>,\n </xsl:if>" \
"</xsl:for-each>\n" \
"<xsl:text>]\n}}</xsl:text>" \
"</xsl:template></xsl:stylesheet>";
const P6CHAR* pData1 =
"<?xml version='1.0' encoding='UTF-8' ?>\n" \
"<staff>" \
"<employee>" \
" <name>Henry Joseph</name>" \
" <hiredate>2007-01-09</hiredate>" \
"</employee>" \
"<employee>" \
" <name>Irvin Joseph</name>" \
" <hiredate>2003-06-12-03:05</hiredate>" \
"</employee>" \
"<employee>" \
" <name>Izzy Joseph</name>" \
" <hiredate>1998-11-03</hiredate>" \
"</employee>" \
"<employee>" \
" <name>Basil Joseph</name>" \
" <hiredate>1998-11-03</hiredate>" \
"</employee>" \
"<employee>" \
" <name>Mark Joseph</name>" \
" <hiredate>2004-07-12-08:00</hiredate>" \
"</employee>" \
"<employee>" \
" <name>Jim Susoy</name>" \
" <hiredate>2004-07-12-08:00</hiredate>" \
"</employee>" \
"</staff>";
// -> JSON data, same as the XML above
const P6CHAR* pData2 =
"{\"staff\": {\n" \
" \"employee\": [\n" \
" {\"name\":\"Henry Joseph\",\n" \
" \"hiredate\":\"2007-01-09\"},\n" \
" {\"name\":\"Irvin Joseph\",\n" \
" \"hiredate\":\"2003-06-12-03:00\"},\n" \
" {\"name\":\"Izzy Joseph\",\n" \
" \"hiredate\":\"1998-11-03:00\"},\n" \
" {\"name\":\"Basil Joseph\",\n" \
" \"hiredate\":\"1998-11-03\"},\n" \
" {\"name\":\"Mark Joseph\",\n" \
" \"hiredate\":\"2004-07-12-08:00\"},\n" \
" {\"name\":\"Jim Susoy\",\n" \
" \"hiredate\":\"2004-07-12-08:00\"}]\n" \
" } }";
// [A] Initialize the components we need
if (P6FAILED( err = p6CreateInstance( NULL, CID_p6XSLT, VALIDATECOMPTR( p6IXSLT, cpXSLT1 ))))
{
printf( "Error: p6IXSLT Initialize failed-1\n" );
return err;
}
if (P6FAILED( err = p6CreateInstance( NULL, CID_p6XSLT, VALIDATECOMPTR( p6IXSLT, cpXSLT2 ))))
{
printf( "Error: p6IXSLT Initialize failed-2\n" );
return err;
}
if (NULL != (pObj = new (std::nothrow) CFileStream() ))
{
pObj->initialize( "example-xslt2-1.txt" );
if (P6FAILED( err = pObj->queryInterface( IID_p6IDataStream, (P6VOID**)&pOutStream1 )))
{
delete pObj;
return err;
}
}
if (NULL != (pObj = new (std::nothrow) CFileStream() ))
{
pObj->initialize( "example-xslt2-2.txt" );
if (P6FAILED( err = pObj->queryInterface( IID_p6IDataStream, (P6VOID**)&pOutStream2 )))
{
pOutStream1->release();
delete pObj;
return err;
}
}
// [B] Run the XSLT processors
err = cpXSLT1->initialize( P6XSLT_NOFLAGS, pOutStream1 ); // | P6XSLT_XMLTRACE );
if (P6SUCCEEDED( err )) err = cpXSLT1->compileTemplates( pTemplate1, pOutStream1 );
bufSize = (P6UINT32) strlen( pData1 );
if (P6SUCCEEDED( err )) err = cpXSLT1->startTransform( pOutStream1, pData1, bufSize, P6TRUE );
err = cpXSLT2->initialize( P6XSLT_USEJSON, pOutStream2 ); // | P6XSLT_XMLTRACE );
if (P6SUCCEEDED( err )) err = cpXSLT2->compileTemplates( pTemplate2, pOutStream2 );
bufSize = (P6UINT32) strlen( pData2 );
if (P6SUCCEEDED( err )) err = cpXSLT2->startTransform( pOutStream2, pData2, bufSize, P6TRUE );
pOutStream1->release();
pOutStream2->release();
if (P6FAILED( err )) printf("example failed due to [ %s ]\n", p6ErrToStr(err,&szErr[0],P6CHARCNT(szErr)));
return err;
}
int main(int argc,char *argv[])
{
P6ERR err = eOk;
if ( P6SUCCEEDED(err = CConsoleStream::createInstance( NULL, VALIDATECOMPTR( p6IDataStream, cpDataStream ))))
{
if ( P6SUCCEEDED(err = p6InitializeLoader( cpDataStream, 9, P6SCLF_NOFLAGS )))
{
err = runXSLT( cpDataStream );
printf( "runXSLT result: [ %x ]\n", err );
}
else printf("ERROR: Failed to initialize the loader [ %x ]\n", err );
}
else printf( "ERROR: Failed to create CConsoleStream [ %x ]\n", err );
return err;
}