MSXML selectNodes SelectSingleNode

I found a nice msxml wrapper class at http://www.codeguru.com/cpp/data/data-misc/xml/article.php/c8287/  which I want to extend for my own application.
I need the function selectsinglenode  and selectNodes, as an extension of the class CXMLMgr.

below you will find by main application made for debugging purpose, the modified CXMLMgr.cpp  and CXMLMgr.h  you will find in the attached file. The final result a can get by calling select nodes and selectsinglenode directly and not from the call.  The xml should be like this:
*******************************
<?xml version="1.0"?>
<info>
      <data>
            <Elements1/>
            <Elements2/>
            <Elements3>
                  <SubElement>
                        <S>Sub Node 1</S>
                        <V>Sub Node 2</V>
                        <x>Sub Node 3</x></SubElement></Elements3>
            <Elementsx>
      <SubElement_x>
            <S>xSub Node 1</S>
            <V>xSub Node 2</V>
            <x>xSub Node 3</x></SubElement_x></Elementsx>
            <Elementsx>
      <SubElement_x>
            <S>xSub Node 1</S>
            <V>xSub Node 2</V>
            <x>xSub Node 3</x></SubElement_x></Elementsx>
            <Elementsx>
      <SubElement_x>
            <S>xSub Node 1</S>
            <V>xSub Node 2</V>
            <x>xSub Node 3</x></SubElement_x></Elementsx>
</data></info>

*************************************************************



/***************************************************************************
*    A Simple DOM-Based XML Manager Class
*    A simple wrapper class using DOM (Document Object Model) to
*    manipulate XML
*    download from   http://www.codeguru.com/cpp/data/data-misc/xml/article.php/c8287/
*
*
*
*   History of revisons
*
*******************************************************************************/


#include "stdafx.h"


#include <iostream>
#include <comutil.h>

#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <map>
#include <vector>  
#include "XMLMgr.h"


 #include <utility>                   // for std::pair
 #include <algorithm>                 // for std::for_each



using namespace std;








void CreateXMLFile( )
{
MSXML2::IXMLDOMElement* pElem;
MSXML2::IXMLDOMNode* pNode;

CXMLMgr xmlMgr;
xmlMgr.Initlize();
xmlMgr.CreateXMLFileHeader();
xmlMgr.CreateRoot("info");

pElem = xmlMgr.GetRoot();
xmlMgr.CreateElement("data" , NULL , pElem);
pElem = xmlMgr.GetLastItemAdded();

   xmlMgr.CreateElement("Elements1" , NULL , pElem);
   xmlMgr.CreateElement("Elements2" , NULL , pElem);
   xmlMgr.CreateElement("Elements3" , NULL , pElem);
   xmlMgr.CreateElement("Elementsx" , NULL , pElem);
   xmlMgr.CreateElement("Elementsx" , NULL , pElem);
   xmlMgr.CreateElement("Elementsx" , NULL , pElem);
 xmlMgr.Save("c:\\test.xml");

}



void AddSingleNodeTest( )
{
  MSXML2::IXMLDOMNode* pNodelevel1;


  int  ret;

  CXMLMgr xmlMgr;
 
  xmlMgr.Initlize();

  xmlMgr.Load("c:\\test.xml");


  MSXML2::IXMLDOMElement* pRoot = xmlMgr.GetRoot();

 
  pNodelevel1 = xmlMgr.GetFirstChild();

 
 
 //  this line of code is fine  
 //  ret = pRoot->selectSingleNode(_bstr_t("//Elements3"), &pNodelevel1 );
 
   //  that what I want not ....
  xmlMgr.SelectSingleNode("//Elements1", pNodelevel1);



   if (S_OK == xmlMgr.CreateElement( "SubElement" ,NULL ,pNodelevel1 ,
                                  true ,1 ))
        {
        // Element Node has been created, now set the sub nodes in it
         MSXML2::IXMLDOMElement *pElement = xmlMgr.GetLastItemAdded();

         xmlMgr.CreateElement( "S" , "Sub Node 1" , pElement ,
                         true , 2);
         xmlMgr.CreateElement( "V" , "Sub Node 2" , pElement ,
                         true , 2);
         xmlMgr.CreateElement( "x" , "Sub Node 3" , pElement ,
                         true , 2);

         // Now add the element in the XMLDOM
         xmlMgr.InsertChild(pElement , pNodelevel1);
      }
   // Save the DOM to file
   
 xmlMgr.Save("c:\\test.xml");
   



}




void AddusingNodeListTest( )
{
  MSXML2::IXMLDOMNode* pNodelevel1;
  MSXML2::IXMLDOMNodeList* pNodeList;


  long  max;
  int  i;
  int  ret;

  CXMLMgr xmlMgr;
 
  xmlMgr.Initlize();

  xmlMgr.Load("c:\\test.xml");


  MSXML2::IXMLDOMElement* pRoot = xmlMgr.GetRoot();

 
  pNodelevel1 = xmlMgr.GetFirstChild();

 //  this line of code is fine  
 // ret = pRoot->selectNodes(_bstr_t("//Elementsx"), &pNodeList );
 
 //  that what I want not ....
 ret = xmlMgr.SelectNodes("//Elementsx", pNodeList);


 pNodeList->get_length(&max);

 for (i=0; i<max; i++)
 {
         pNodeList->get_item(i, &pNodelevel1);

 
 
 

 



   if (S_OK == xmlMgr.CreateElement( "SubElement_x" ,NULL ,pNodelevel1 ,
                                  true ,1 ))
        {
        // Element Node has been created, now set the sub nodes in it
         MSXML2::IXMLDOMElement *pElement = xmlMgr.GetLastItemAdded();

         xmlMgr.CreateElement( "S" , "xSub Node 1" , pElement ,
                         true , 2);
         xmlMgr.CreateElement( "V" , "xSub Node 2" , pElement ,
                         true , 2);
         xmlMgr.CreateElement( "x" , "xSub Node 3" , pElement ,
                         true , 2);

         // Now add the element in the XMLDOM
         xmlMgr.InsertChild(pElement , pNodelevel1);
      }
   // Save the DOM to file
 
 }
 xmlMgr.Save("c:\\test.xml");
   



}












//
//  Main program
//  


int main()
{
 
   
   




   

   //------------------------------------------------------------------------
   //------------------------------------------------------------------------
   //------------------------------------------------------------------------
   //-------------------


    printf ("  create the XML  file ...              \n");

    CreateXMLFile ();

    printf ("  write the XML  file (1) ...             \n");

    AddSingleNodeTest();


    printf ("  write the XML  file (2) ...             \n");

    AddusingNodeListTest();

 

    system("pause");



}
HRESULT CXMLMgr::SelectSingleNode(LPCSTR lpcstrNodeName,  MSXML2::IXMLDOMNode* pParentNode )
{
	assert (lpcstrNodeName != NULL);
	
	HRESULT hr = E_FAIL;
	
	
 
	hr = m_pXMLRoot->selectSingleNode(_bstr_t( lpcstrNodeName ),&pParentNode );
 
   //  ret = pRoot->selectSingleNode(_bstr_t("//Elements3"), &pNodelevel1 );
 
 
 
	return hr;
}
 
 
 
HRESULT CXMLMgr::SelectNodes(LPCSTR lpcstrNodeName,  MSXML2::IXMLDOMNodeList* pNodeList )
{
	assert (lpcstrNodeName != NULL);
	
	HRESULT hr = E_FAIL;
	
	
 
	hr = m_pXMLRoot->selectNodes(_bstr_t( lpcstrNodeName ),&pNodeList );
 
   
 
	return hr;
}
 
 
 
 
 
 
 
 
 
 
/*$ ******************************************************************************
					Method Name				AddWhiteSpaceToNode
 
					Parameters				[in] MSXML2::IXMLDOMDocument* pDOMDoc
												Document pointer
 
											[in] BSTR bstrWs
												White space BSTR
								
											[in] MSXML2::IXMLDOMNode* pNode
												Node to which white space is required to be created
 
					Return					None
 
					Description				Create white spaces
********************************************************************************** */
void CXMLMgr::AddWhiteSpaceToNode(MSXML2::IXMLDOMDocument* pDOMDoc, BSTR bstrWs, MSXML2::IXMLDOMNode* pNode)
{
	MSXML2::IXMLDOMText *pws  = NULL;
	MSXML2::IXMLDOMNode *pBuf = NULL;
    
	pDOMDoc->createTextNode(bstrWs,&pws);
    pNode->appendChild(pws,&pBuf);
 
	if (pws)
		pws->Release();
 
	if (pBuf)
		pBuf->Release();
}
 
/*$ ******************************************************************************
					Method Name			CreateNode	
 
					Parameters			[in] LPCSTR
											A string specifying the name for the new element node
 
										[in] MSXML2::IXMLDOMElement*
											The IXMLDOMElement interface for the new element 
 
					Return				MSXML2::IXMLDOMElement*
											New element created
 
					Description			Creates an element node using the specified name
********************************************************************************** */
MSXML2::IXMLDOMElement* CXMLMgr::CreateNode(LPCSTR lpcstrRootName , MSXML2::IXMLDOMElement* pNode )
{
	assert (lpcstrRootName != NULL);
 
	HRESULT hr = E_FAIL;
	BSTR bstr;
	wi_CharToBSTR(lpcstrRootName , bstr);
   
	// Putting the name of the element in the DOM
	hr = m_pXMLDomDoc->createElement(bstr, &pNode);
 
	SysFreeString(bstr);
 
	return pNode;
}
 
/*$ ******************************************************************************
					Method Name			SetNodeText	
 
					Parameters			[in] LPCSTR
											Node text to set
 
										[in] MSXML2::IXMLDOMElement*
											Node, which text is required to be set
 
					Return				HRESULT
											S_OK (on Success)
											E_FAIL (on Error)
 
					Description			Set the text of the specified node
********************************************************************************** */
HRESULT CXMLMgr::SetNodeText(LPCSTR lpcstrText , MSXML2::IXMLDOMElement* pNode)
{
	assert (lpcstrText != NULL);
	assert (pNode  != NULL);
 
	HRESULT hr = E_FAIL;
	BSTR bstr;
	wi_CharToBSTR(lpcstrText , bstr);
 
	// Writing Element To DOM
	hr = pNode->put_text(bstr);
 
	SysFreeString(bstr);
 
	return hr;
}
 
/*$ ******************************************************************************
					Method Name			SetIndentLevel		
 
					Parameters			[in] int
											Indend level
											
										[in] MSXML2::IXMLDOMNode*
											Node, which indend level is required to be set
					Return				None
 
					Description			---
********************************************************************************** */
void CXMLMgr::SetIndentLevel(int nLevel , MSXML2::IXMLDOMNode* pParentNode)
{
	assert (nLevel >= 0);
	assert (pParentNode != NULL);
 
	BSTR bstr;
	std::string strIndenter = "\n";
 
	for (int nCount = 0; nCount < nLevel; nCount++)
		strIndenter += "\t";
 
	wi_CharToBSTR( strIndenter.c_str() , bstr);
 
	AddWhiteSpaceToNode(m_pXMLDomDoc, bstr, pParentNode);
 
	SysFreeString(bstr);
}
 
/*$ ******************************************************************************
					Method Name			ReplaceElement	
 
					Parameters			[in] MSXML2::IXMLDOMElement* pNewElement
											New element
 
										[in] MSXML2::IXMLDOMElement* pOldElement
											Element to be replaced
 
										[in] MSXML2::IXMLDOMNode* pParent
											Parent which contains the element that is required to be replaced
 
					Return				HRESULT
											S_OK (on Success)
											E_FAIL (on Error)
 
					Description			Replace an existing element with the new element.
********************************************************************************** */
HRESULT CXMLMgr::ReplaceElement(MSXML2::IXMLDOMElement* pNewElement , MSXML2::IXMLDOMElement* pOldElement , MSXML2::IXMLDOMNode* pParent)
{
	assert (pNewElement != NULL);
	assert (pOldElement != NULL);
 
	HRESULT hr = E_FAIL;
 
	MSXML2::IXMLDOMNode* pElementReplaced = NULL;
 
	hr = pParent->replaceChild(pNewElement , pOldElement , &pElementReplaced);
 
	return hr;
}
 
/*$ ******************************************************************************
					Method Name			RemoveElement	
 
					Parameters			[in] MSXML2::IXMLDOMElement* pElementToRemove
											Element to be removed
 
										[in] MSXML2::IXMLDOMNode* pParent
											Parent that contains the element, required to be removed
 
					Return				HRESULT
											S_OK (on Success)
											E_FAIL (on Error)
 
					Description			Remove specified element from the parent node
********************************************************************************** */
HRESULT CXMLMgr::RemoveElement(MSXML2::IXMLDOMElement* pElementToRemove , MSXML2::IXMLDOMNode* pParent)
{
	assert (pElementToRemove != NULL);
	assert (pParent != NULL);
 
	HRESULT hr = E_FAIL;
 
	MSXML2::IXMLDOMNode * pOutNode = NULL;
	hr = pParent->removeChild(pElementToRemove , &pOutNode);
 
	return hr;
}
 
/*$ ******************************************************************************
					Method Name			RemoveElement	
 
					Parameters			[in] MSXML2::IXMLDOMElement*
											Element to be removed. It will determine its pareent itself
 
					Return				HRESULT
											S_OK (on Success)
											E_FAIL (on Error)
	
					Description			Remove a specified element
********************************************************************************** */
HRESULT CXMLMgr::RemoveElement(MSXML2::IXMLDOMElement* pElementToRemove)
{
	assert (pElementToRemove != NULL);
	
	MSXML2::IXMLDOMNode* pParent = GetParent(pElementToRemove);
	assert (pParent != NULL);
 
	HRESULT hr = E_FAIL;
 
	MSXML2::IXMLDOMNode * pOutNode = NULL;
	hr = pParent->removeChild(pElementToRemove , &pOutNode);
 
	return hr;
}
 
/*$ ******************************************************************************
					Method Name			GetParent	
 
					Parameters			[in] MSXML2::IXMLDOMElement*
											Element to which parent is required
 
					Return				MSXML2::IXMLDOMNode*
											Parent of the element
 
					Description			Return the parent of the specified element
********************************************************************************** */
MSXML2::IXMLDOMNode* CXMLMgr::GetParent(MSXML2::IXMLDOMElement* pElement) const
{
	assert (pElement != NULL);
 
	MSXML2::IXMLDOMNode* pNode = NULL;
	pElement->get_parentNode(&pNode);
 
	return pNode;
}
 
/*$ ******************************************************************************
					Method Name			GetChild
 
					Parameters			[in] const long lIndex
											Index of the child to get
								
										[in] MSXML2::IXMLDOMNodeList*
											Parent list, that contains the child
 
					Return				MSXML2::IXMLDOMNode*
											child pointer
 
					Description			Get the child element from a parent list, which index is specified.
********************************************************************************** */
MSXML2::IXMLDOMNode* CXMLMgr::GetChild(const long lIndex , MSXML2::IXMLDOMNodeList* pList) const
{
	assert (lIndex >= 0);
	assert (pList != NULL);
 
	MSXML2::IXMLDOMNode* pNode;
	pList->get_item(lIndex , &pNode);
 
	return pNode;
}
 
/*$ ******************************************************************************
					Method Name			Destroy
					Parameters			None
					Return				None
					Description			Release resources
********************************************************************************** */
void CXMLMgr::Destroy()
{
	Release();
	::CoUninitialize();
 
	delete m_pBuffer;
	m_pBuffer = NULL;
}

Open in new window

LVL 8
BdLmAsked:
Who is Participating?
 
Infinity08Connect With a Mentor Commented:
>>  //  that what I want not ....  not fine
>>  ret = xmlMgr.SelectNodes("//Elementsx", pNodeList);


HRESULT CXMLMgr::SelectNodes(LPCSTR lpcstrNodeName,  MSXML2::IXMLDOMNodeList** pNodeList )               // <--- double pointer
{
	assert (lpcstrNodeName != NULL);
	
	HRESULT hr = E_FAIL;
	
	
 
	hr = m_pXMLRoot->selectNodes(_bstr_t( lpcstrNodeName ), pNodeList );        // <--- don't take the address
 
   
 
	return hr;
}
 
 
// call like this :
 
ret = xmlMgr.SelectNodes("//Elementsx", &pNodeList);

Open in new window

0
 
Infinity08Commented:
And what's the problem / question ?
0
 
BdLmAuthor Commented:
I'm in troble transfering the 2 LInes of code to the xmlmgr class:
(1)
//  this line of code is fine  
 // ret = pRoot->selectNodes(_bstr_t("//Elementsx"), &pNodeList );
 
 //  that what I want not ....  not fine
 ret = xmlMgr.SelectNodes("//Elementsx", pNodeList);

and

(2)

//  this line of code is fine  
 //  ret = pRoot->selectSingleNode(_bstr_t("//Elements3"), &pNodelevel1 );
 
   //  that what I want not ....
  xmlMgr.SelectSingleNode("//Elements1", pNodelevel1);

do I have to change the definition from  MSXML2::IXMLDOMNode* pParentNode  to
 MSXML2::IXMLDOMNode** pParentNode ?

0
 
Infinity08Commented:
Similarly for SelectSingleNode.
0
 
BdLmAuthor Commented:
now my code runs ...   .-))
0
All Courses

From novice to tech pro — start learning today.