Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ex-dom-3.cpp
#include "p6loader.h"
#include "p6domxml.h"
#include "cconsolestream.h"
#include "cfilestream.h"
using namespace P6R;
using namespace P6EXAMPLES;
P6DECLARE_CID( p6DOMXML );
P6DECLARE_CID( p6XpathExpression );
P6DECLARE_IID( IFileStreamInit );
namespace {
P6R::P6ERR getFileStream(const P6R::P6WCHAR *pszFilepath,P6R::p6IDataStream **ppIface)
{
P6ERR err;
if(P6SUCCEEDED(err = CFileStream::createInstance(NULL,VALIDATECOMPTR(IFileStreamInit,cpFileInit)))) {
if(P6SUCCEEDED(err = cpFileInit->initialize(pszFilepath))) {
err = cpFileInit.queryInterface(IID_p6IDataStream,ppIface);
}
}
return err;
}
P6R::P6ERR getDOMXML(P6R::p6IDataStream *pOutStream,P6R::p6IDOMXML **ppIface)
{
P6ERR err;
if(P6SUCCEEDED(err = p6CreateInstance(NULL,CID_p6DOMXML,VALIDATECOMPTR(p6IDOMXML,cpDOM)))) {
if(P6SUCCEEDED(err = cpDOM->initialize(P6DOMXML_NOFLAGS,pOutStream))) {
//
// Using detach() saves a reference counting operation
// and gives ownership to *ppIface.
//
cpDOM.detach(ppIface);
}
}
return err;
}
P6R::P6ERR getXPathEngine(P6R::p6IDataStream *pOutStream,P6R::p6IXpathExpression **ppIface)
{
P6ERR err;
if(P6SUCCEEDED(err = p6CreateInstance(NULL,CID_p6XpathExpression,VALIDATECOMPTR(p6IXpathExpression,cpXPath)))) {
if(P6SUCCEEDED(err = cpXPath->initialize(P6XPATH_NOFLAGS,pOutStream))) {
//
// Using detach() saves a reference counting operation
// and gives ownership to *ppIface.
//
cpXPath.detach(ppIface);
}
}
return err;
}
// Notice how we use the XPath components directly. XPath is also used in our XSLT processor.
// Notice how we are using an XPath expression to sort a set of DOM tree nodes.
//
P6R::P6ERR runDOM( P6R::p6IConsole *pConsole, p6IDataStream *pStreamDebug )
{
p6ComPtr<p6IXMLNode> cpAnotherChild;
const P6WCHAR *pString = NULL;
P6UINT32 length = 0;
P6UINT32 count = 0;
P6INT32 retval = 0;
P6UINT32 bufSize = 0;
P6ERR err = eOk;
P6ARG args[1];
const P6CHAR* pXML =
"<?xml version='1.0' encoding='UTF-8' ?>" \
"<catalog>" \
"<item>" \
" <name SKU='ABTEY837364'>Reynolds Ouzo Comp Integrated Fork</name>" \
" <price>199</price>" \
"</item>" \
"<item>" \
" <price>299</price>" \
" <name SKU='Z123647ydhgetr'>Easton EC-90 SLX Fork</name>" \
"</item>" \
"<item>" \
" <price>499</price>" \
" <name SKU='JDHEWU73736dhdhfgv'>Look HSC-5 SL Fork</name>" \
"</item>" \
"</catalog>";
// [A] Create & initialize the components we need
if (P6FAILED( err = p6GetRuntimeIface( VALIDATECOMPTR( p6ISafeString, cpStr )))) return err;
if (P6FAILED( err = getFileStream(P6CTEXT("ctestnodesort.html.html"),cpOutStream.addressof()))) return err;
if (P6FAILED( err = getDOMXML(cpOutStream,cpDOM.addressof()))) return err;
if (P6FAILED( err = getXPathEngine(NULL,cpXPath.addressof()))) return err;
// [B] Stream the XML document into the DOM parser (can be done with one or many calls to processStream, see SAX2-2 example)
err = cpDOM->parse( cpStream.addressof() );
if (P6SUCCEEDED( err )) err = cpStream->beginStream();
cpStr->strlen( pXML, 100000, &bufSize );
if (P6SUCCEEDED( err )) err = cpStream->processStream( pXML, bufSize );
if (P6SUCCEEDED( err ))err = cpStream->endStream();
cpStream = NULL; // Tell the smart pointer to release the interface
// [C] Sort the nodes returned by use of an XPath expression
if (P6SUCCEEDED( err ))
{
// -> get back a sequence of nodes
err = cpXPath->compileExpression( P6CTEXT("/catalog/item/name"), 18, NULL );
err = cpXPath->eval( cpDOM, NULL, NULL, &result );
if (result.type != P6XPATH_TYPE_SET) { printf( "Expected %d but got %d\n", P6XPATH_TYPE_SET, result.type ); return eFail; }
if (NULL == result.pNodeSet) return eFail;
// -> now sort the returned nodes by their SKU attribute, ** sort by strings **, notice the use of P6DOMNODE_DESCENDING
if (P6FAILED( err = cpXPath->compileExpression( P6CTEXT("@SKU"), 4, NULL ))) return err;
{
err = cpSort->sortByExpression( cpDOM, P6DOMNODE_DESCENDING, cpXPath );
cpSort = NULL; // Tell p6ComPtr<> to release() the interface, we no longer need it.
}
count = 0;
while( P6SUCCEEDED( err ) && P6SUCCEEDED( err = result.pNodeSet->next( cpChild.addressofWithRelease() )))
{
err = cpChild->childAt( 0, cpAnotherChild.addressofWithRelease() );
if (P6SUCCEEDED( err ) && P6SUCCEEDED( err = cpAnotherChild->getValue( &pString, &length )))
{
switch( count ) {
case 0:
retval = -1;
err = cpStr->wstrncmp( P6CTEXT("Easton EC-90 SLX Fork"), pString, 21, &retval );
if (0 != retval) {
P6BWCSTR bStr;
bStr.pString = pString;
bStr.length = length;
P6AI_BWCSTR(&args[0],&bStr);
pConsole->writeStdout("Expected [ Easton EC-90 SLX Fork ] but got [ %1$ ]\n",&args[0],1,NULL);
return eFail;
}
break;
case 1:
//printf( "value of node1.1 [%ls] %d\n", pString, length );
retval = -1;
err = cpStr->wstrncmp( P6CTEXT("Look HSC-5 SL Fork"), pString, 18, &retval );
if (0 != retval) {
P6BWCSTR bStr;
bStr.pString = pString;
bStr.length = length;
P6AI_BWCSTR(&args[0],&bStr);
pConsole->writeStdout("Expected [ Look HSC-5 SL Fork ] but got [ %1$ ]\n",&args[0],1,NULL);
return eFail;
}
break;
case 2:
//printf( "value of node1.2 [%ls] %d\n", pString, length );
retval = -1;
err = cpStr->wstrncmp( P6CTEXT("Reynolds Ouzo Comp Integrated Fork"), pString, 34, &retval );
if (0 != retval) {
P6BWCSTR bStr;
bStr.pString = pString;
bStr.length = length;
P6AI_BWCSTR(&args[0],&bStr);
pConsole->writeStdout("Expected [ Reynolds Ouzo Comp Integrated Fork ] but got [ %1$ ]\n",&args[0],1,NULL);
return eFail;
}
break;
}
}
count++;
}
if (eEndOfRecord == err) return eOk;
}
if (P6FAILED( err )) {
P6AI_ERR(&args[0],err);
pConsole->writeStdout("ERROR: Example failed with [ %1$ ]\n", &args[0], 1, NULL );
}
return err;
}
} // namespace
int main(int argc,char *argv[])
{
P6ERR err = eOk;
p6ComPtr<p6IDataStream> cpDebugStream;
P6ARG args[1];
if(P6SUCCEEDED(err = CConsoleStream::createInstance(NULL,VALIDATECOMPTR(p6IDataStream,cpDebugStream)))) {
if(P6SUCCEEDED(err = p6InitializeLoader(cpDebugStream,9,P6SCLF_NOFLAGS))) {
err = runDOM( cpConsole, cpDebugStream );
P6AI_ERR(&args[0],err);
cpConsole->writeStdout("runDOM result: [ %1$ ]\n",&args[0],1,NULL);
//
// Make sure to release the console interface
// before calling p6CleanupLoader() !! In this
// instance we don't let the smart pointer
// handle the cleanup.
//
cpConsole = NULL;
}
else printf("ERROR: Failed to retrieve console interface [ %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;
}