Using this class you can read tag and value of a XML file and add the values in to a std::list.
//ReadXML.h
#include
#include
#include
#include
#import
class CReadXML
{
public:
CReadXML();
~CReadXML();
HRESULT CreateAndInitDOM(IXMLDOMDocument **ppDoc);
HRESULT VariantFromString(PCWSTR wszValue, VARIANT &Variant);
void LoadDOM( std::string pFileName, std::list
std::wstring String2WS (const std::string& s);
std::string ConvertWCSToMBS(const wchar_t* pstr, long wslen);
std::string ConvertBSTRToString(BSTR bstr);
BOOL CheckSubNodes( IXMLDOMNode *pNode );
void ReadNodeValues( IXMLDOMNode *pNode, std::list
void ReadSubNode( IXMLDOMNode *pNode, std::list
};
//ReadXML.cpp
#include
#include "ReadXML.h"
//http://msdn.microsoft.com/en-us/library/windows/desktop/ms765465(v=vs.85).aspx
// Macro to verify memory allcation.
#define CHK_ALLOC(p) do { if (!(p)) { hr = E_OUTOFMEMORY; goto CleanUp; } } while(0)
// Macro that calls a COM method returning HRESULT value.
#define CHK_HR(stmt) do { hr=(stmt); if (FAILED(hr)) goto CleanUp; } while(0)
// Macro that releases a COM object if not NULL.
#define SAFE_RELEASE(p) do { if ((p)) { (p)->Release(); (p) = NULL; } } while(0)
CReadXML::CReadXML()
{
}
CReadXML::~CReadXML()
{
}
// Helper function to create a DOM instance.
HRESULT CReadXML::CreateAndInitDOM(IXMLDOMDocument **ppDoc)
{
HRESULT hr = CoCreateInstance( __uuidof(MSXML::DOMDocument30), NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)ppDoc);
if (SUCCEEDED(hr))
{
// these methods should not fail so don't inspect result
(*ppDoc)->put_async(VARIANT_FALSE);
(*ppDoc)->put_validateOnParse(VARIANT_FALSE);
(*ppDoc)->put_resolveExternals(VARIANT_FALSE);
}
return hr;
//NOT WORKING, IF "xmlns=" IS IN XML FILE
//HRESULT hr = CoCreateInstance(__uuidof(MSXML::DOMDocument60), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(ppDoc));
// if (SUCCEEDED(hr))
// {
// // these methods should not fail so don't inspect result
// (*ppDoc)->put_async(VARIANT_FALSE);
// (*ppDoc)->put_validateOnParse(VARIANT_FALSE);
// (*ppDoc)->put_resolveExternals(VARIANT_FALSE);
// }
}
// Helper function to create a VT_BSTR variant from a null terminated string.
HRESULT CReadXML::VariantFromString(PCWSTR wszValue, VARIANT &Variant)
{
HRESULT hr = S_OK;
BSTR bstr = SysAllocString(wszValue);
CHK_ALLOC(bstr);
V_VT(&Variant) = VT_BSTR;
V_BSTR(&Variant) = bstr;
CleanUp:
return hr;
}
std::wstring CReadXML::String2WS (const std::string& s)
{
std::wstringstream ws;
ws << s.c_str();
std::wstring sLogLevel = ws.str();
return sLogLevel;
// std::wstring ws;
//ws.assign (s.begin (), s.end ());
// return ws;
}
std::string CReadXML::ConvertWCSToMBS(const wchar_t* pstr, long wslen)
{
int len = ::WideCharToMultiByte(CP_ACP, 0, pstr, wslen, NULL, 0, NULL, NULL);
std::string dblstr(len, '?');
len = ::WideCharToMultiByte(CP_ACP, 0 /* no flags */,
pstr, wslen /* not necessary NULL-terminated */,
&dblstr[0], len,
NULL, NULL /* no default char */);
return dblstr;
}
std::string CReadXML::ConvertBSTRToString(BSTR bstr)
{
int wslen = ::SysStringLen(bstr);
return ConvertWCSToMBS((wchar_t*)bstr, wslen);
}
void CReadXML::LoadDOM( std::string pFileName, std::list
{
HRESULT hr = S_OK;
IXMLDOMDocument *pXMLDom = NULL;
IXMLDOMParseError *pXMLErr = NULL;
IXMLDOMNodeList *NodeList = NULL;
IXMLDOMNode *pNode = NULL;
std::wstring wspFileName;
BSTR bstrXML = NULL;
BSTR bstrErr = NULL;
BSTR bstrQuery2 = NULL;
VARIANT_BOOL varStatus;
VARIANT varFileName;
VariantInit(&varFileName);
//Initialize COM Library:
CoInitialize(NULL);
CHK_HR(CreateAndInitDOM(&pXMLDom));
wspFileName = String2WS(pFileName);
// XML file name to load
CHK_HR(VariantFromString( wspFileName.c_str(), varFileName));
CHK_HR(pXMLDom->load(varFileName, &varStatus));
if (varStatus == VARIANT_TRUE)
{
CHK_HR(pXMLDom->get_xml(&bstrXML));
//printf("XML DOM loaded from stocks.xml:\n%S\n", bstrXML);
bstrQuery2 = SysAllocString(L"Object"); // For find the tag Object. Please replace this with your tag name. If you need to read all values, then replace "Object" with " ". But the problem is that, then each tags consider as each item, can not separate the child nodes. For a better out put specify the tag name, where you want to start.
CHK_ALLOC(bstrQuery2);
CHK_HR(pXMLDom->getElementsByTagName(bstrQuery2, &NodeList));
if(NodeList)
{
//get the length of node-set
long length = 0;
CHK_HR(NodeList->get_length(&length));
for (long i = 0; i < length; i++)
{
if ( pNode ) pNode->Release();
CHK_HR( NodeList->get_item(i, &pNode) );
if(pNode )
{
if( CheckSubNodes( pNode ) == TRUE )
{
ReadSubNode( pNode, values );
}
else
{
ReadNodeValues( pNode, values );
}
}
}
}
}
else
{
// Failed to load xml, get last parsing error
CHK_HR(pXMLDom->get_parseError(&pXMLErr));
CHK_HR(pXMLErr->get_reason(&bstrErr));
printf("Failed to load DOM from %S. %S\n", varFileName, bstrErr);
}
CleanUp:
SAFE_RELEASE(pXMLDom);
SAFE_RELEASE(pXMLErr);
SAFE_RELEASE(NodeList);
SAFE_RELEASE(pNode);
SysFreeString(bstrXML);
SysFreeString(bstrErr);
SysFreeString(bstrQuery2);
VariantClear(&varFileName);
}
void CReadXML::ReadSubNode( IXMLDOMNode *pNode, std::list
{
HRESULT hr = S_OK;
HRESULT hResult;
IXMLDOMNode *pIAttrNode = NULL;
IXMLDOMNodeList *NodeList = NULL;
IXMLDOMNamedNodeMap *pDOMNamedNodeMap = NULL;
long length = 0;
std::pair
if( pNode )
{
CHK_HR( pNode->get_childNodes(&NodeList) );
if( NodeList )
{
CHK_HR( NodeList->get_length(&length) );
for( int i = 0; i < length; i++ )
{
if (pIAttrNode) pIAttrNode->Release();
CHK_HR( NodeList->get_item(i, &pIAttrNode));
if(pIAttrNode )
{
if( CheckSubNodes( pIAttrNode ) == TRUE )
{
ReadSubNode( pIAttrNode, values );
}
else
{
ReadNodeValues( pIAttrNode, values );
}
}
}
}
}
CleanUp:
SAFE_RELEASE(NodeList);
}
BOOL CReadXML::CheckSubNodes( IXMLDOMNode *pNode )
{
HRESULT hr = S_OK;
IXMLDOMNodeList *NodeList = NULL;
long length = 0;
VARIANT_BOOL varStatus = FALSE;
if( pNode )
{
CHK_HR( pNode->get_childNodes(&NodeList) );
if( NodeList )
{
CHK_HR( NodeList->get_length(&length) );
if( length > 0 )
varStatus = TRUE;
else
varStatus = FALSE;
}
}
CleanUp:
SAFE_RELEASE(NodeList);
return varStatus;
}
void CReadXML::ReadNodeValues( IXMLDOMNode *pNode, std::list
{
HRESULT hr = S_OK;
IXMLDOMNode* pParNode = NULL;
//Variables to store item's name, parent, text and node type:
BSTR bstrItemText, bstrItemNode, bstrNodeType;
std::pair
CHK_HR( pNode->get_nodeTypeString(&bstrNodeType));
//We process only elements (nodes of "Text" type):
BSTR temp = L"text";
if (lstrcmp((LPCTSTR)bstrNodeType, (LPCTSTR)temp)==0)
{
CHK_HR( pNode->get_parentNode( &pParNode ) );
if( pParNode )
{
CHK_HR( pParNode->get_nodeName(&bstrItemNode) );
//printf("Text: %ls\n", bstrItemNode);
CHK_HR( pNode->get_text(&bstrItemText) );
//printf("Text: %ls\n", bstrItemText);
pPair.first = ConvertBSTRToString(bstrItemNode);
pPair.second = ConvertBSTRToString(bstrItemText);
values.push_back( pPair);
}
}
CleanUp:
SAFE_RELEASE(pParNode);
}
For using this class create a C++ application and add the above files into that application. After that create an object of the class "CReadXML" and call the function "LoadDOM".
eg:
std::list
CReadXML* pCReadXML = new CReadXML();
pCReadXML->LoadDOM("response_tunnel.xml", values);
After the function call you will get the values of XML file in the std::list values!.
Enjoy...!
No comments:
Post a Comment