Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ex-dom-5.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.
//
static P6R::P6ERR runDOM( P6R::p6IConsole *pConsole, p6IDataStream *pStreamDebug )
{
const P6WCHAR *pString = NULL;
P6INT32 retval = 0;
P6UINT32 length = 0;
P6UINT32 bufSize = 0;
P6ERR err = eOk;
P6ARG args[1];
// -> notice that this JsonML document is well formed (i.e., has a top level element
// -> where JSON documents do not have top level elements)
const P6CHAR* pJsonML1 =
"[ \"table\", " \
" { \"class\" : \"test-table\", " \
" \"style\" : \"background-color:purple\" }, " \
" [ \"row1\", \"row1-value\" ], " \
" [ \"row2\" ], " \
" \"mixed content has text anywhere\", " \
" [ \"ro";
const P6CHAR* pJsonML2 =
"w3\", { \"id\" : 2345 } ]," \
" [ \"row4\", " \
" [ \"column1\", 5 ], " \
" [ \"column2\", \"10\" ] " \
" ]," \
" \"test text\" " \
"]";
// [A] Create & initialize the components we need
if (P6FAILED( err = p6GetRuntimeIface( VALIDATECOMPTR( p6ISafeString, cpStr )))) return err;
if (P6FAILED( err = getFileStream(P6CTEXT("ctestjsonml.xml"),cpOutStream1.addressof()))) return err;
if (P6FAILED( err = getFileStream(P6CTEXT("ctestjsonml.txt"),cpOutStream2.addressof()))) return err;
if (P6FAILED( err = getDOMXML(pStreamDebug,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( pJsonML1, 100000, &bufSize );
if (P6SUCCEEDED( err )) err = cpStream->processStream( pJsonML1, bufSize );
cpStr->strlen( pJsonML2, 100000, &bufSize );
if (P6SUCCEEDED( err )) err = cpStream->processStream( pJsonML2, bufSize );
if (P6SUCCEEDED( err ))err = cpStream->endStream();
cpStream = NULL; // Tell p6ComPtr<> to release() the interface.
// [C] Use XPath 2.0 to access the JsonML document
// -> check simple node lookup
// -> notice that JsonML has a top level node (unlike JSON documents), and thus the previous use of "/JSON-document" at the front of an XPath expression is not necessary
err = cpXPath->compileExpression( P6CTEXT("/table/row4/column1"), 19, NULL );
err = cpXPath->eval( cpDOM, NULL, NULL, &result );
result.pNodeSet->reset();
err = result.pNodeSet->next( cpNode.addressofWithRelease() );
if (P6SUCCEEDED( err ))
{
err = cpNode->getName( &pString, &length );
if (P6FAILED( err )) {
P6AI_ERR(&args[0],err);
pConsole->writeStdout("getName failed [ %1$ ]\n",&args[0],1,NULL);
return eFail;
}
retval = -1;
err = cpStr->wstrncmp( P6CTEXT("column1"), pString, 7, &retval );
if (0 != retval) {
P6BWCSTR bStr;
bStr.pString = pString;
bStr.length = length;
P6AI_BWCSTR(&args[0],&bStr);
pConsole->writeStdout("Error: expected [ column1 ] but got [ %1$ ]\n",&args[0],1,NULL);
return eFail;
}
err = cpNode->resetChild();
if (P6FAILED( err )) {
P6AI_ERR(&args[0],err);
pConsole->writeStdout("resetChild() failed [ %1$ ]\n",&args[0],1,NULL);
return err;
}
err = cpNode->nextChild( cpChild.addressofWithRelease() );
if (P6FAILED( err )) {
P6AI_ERR(&args[0],err);
pConsole->writeStdout("nextChild() failed [ %1$ ]\n",&args[0],1,NULL);
return err;
}
err = cpChild->getValue( &pString, &length );
if (P6FAILED( err )) {
P6AI_ERR(&args[0],err);
pConsole->writeStdout("getValue() failed [ %1$ ]\n",&args[0],1,NULL);
return err;
}
retval = -1;
err = cpStr->wstrncmp( P6CTEXT("5"), pString, 1, &retval );
if (0 != retval) {
P6BWCSTR bStr;
bStr.pString = pString;
bStr.length = length;
P6AI_BWCSTR(&args[0],&bStr);
pConsole->writeStdout("Error: expected [ 5 ] but got [ %1$ ]\n",&args[0],1,NULL);
return eFail;
}
}
if (NULL != result.pNodeSet) result.pNodeSet->release();
// [D] Show how XPath 2.0 can be used to extract a JsonML's attribute value
err = cpXPath->compileExpression( P6CTEXT("/table/self::@style"), 19, NULL );
err = cpXPath->eval( cpDOM, NULL, NULL, &result );
result.pNodeSet->reset();
err = result.pNodeSet->next( cpNode.addressofWithRelease() );
if (P6SUCCEEDED( err ))
{
err = cpNode->getName( &pString, &length );
if (P6FAILED( err )) {
P6AI_ERR(&args[0],err);
pConsole->writeStdout("getName() failed [ %1$ ]\n",&args[0],1,NULL);
return err;
}
retval = -1;
err = cpStr->wstrncmp( P6CTEXT("style"), pString, 5, &retval );
if (0 != retval) {
P6BWCSTR bStr;
bStr.pString = pString;
bStr.length = length;
P6AI_BWCSTR(&args[0],&bStr);
pConsole->writeStdout("Error: expected [ style ] but got [ %1$ ]\n",&args[0],1,NULL);
return eFail;
}
err = cpNode->resetChild();
if (P6FAILED( err )) {
P6AI_ERR(&args[0],err);
pConsole->writeStdout("resetChild() failed [ %1$ ]\n",&args[0],1,NULL);
return err;
}
err = cpNode->nextChild( cpChild.addressofWithRelease() );
if (P6FAILED( err )) {
P6AI_ERR(&args[0],err);
pConsole->writeStdout("nextChild() failed [ %1$ ]\n",&args[0],1,NULL);
return err;
}
err = cpChild->getValue( &pString, &length );
if (P6FAILED( err )) {
P6AI_ERR(&args[0],err);
pConsole->writeStdout("getValue() failed [ %1$ ]\n",&args[0],1,NULL);
return err;
}
retval = -1;
err = cpStr->wstrncmp( P6CTEXT("background-color:purple"), pString, 23, &retval );
if (0 != retval) {
P6BWCSTR bStr;
bStr.pString = pString;
bStr.length = length;
P6AI_BWCSTR(&args[0],&bStr);
pConsole->writeStdout("Error: expected [ background-color:purple ] but got [ %1$ ]\n",&args[0],1,NULL);
return eFail;
}
}
if (NULL != result.pNodeSet) result.pNodeSet->release();
// [E] output the document in several formats
err = cpDOM->output( cpOutStream1, P6DOMOUTPUT_XML );
err = cpDOM->output( cpOutStream2, P6DOMOUTPUT_JSONML );
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;
}