#include "StdAfx.h"
#include "../../Include/XMLParse/XMLParser.h"
#include <algorithm>
#define _MAX_BUF_SIZE_ 1024
CXMLParser::CXMLParser()
{
Initialize();
}
CXMLParser::CXMLParser( const char * pFileName )
{
m_strXmlFileName = pFileName;
LoadXml( pFileName, "rootname" );
}
CXMLParser::~CXMLParser()
{
if( NULL != m_XmlDocPtr )
{
m_XmlDocPtr.Detach();
m_XmlDocPtr = NULL;
}
CoUninitialize();
}
static bool FileExist( const char* pszFileName )
{
bool bExist = false;
HANDLE hFile;
if ( NULL != pszFileName )
{
// Use the preferred Win32 API call and not the older OpenFile.
hFile = CreateFile( pszFileName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0 );
if ( INVALID_HANDLE_VALUE != hFile )
{
// If the handle is valid then the file exists.
CloseHandle( hFile );
bExist = true;
}
}
return ( bExist );
}
/// public Implementation
bool CXMLParser::LoadXml( const char * pFileName, const char * pRootName )
{
if( NULL != m_XmlDocPtr )
{
m_XmlDocPtr->Release();
m_XmlDocPtr.Detach();
}
VARIANT_BOOL vbSuccessful;
m_strXmlFileName = pFileName;
// initialize the Xml parser
HRESULT hr = m_XmlDocPtr.CreateInstance( __uuidof(DOMDocument30) );
//__uuidof(DOMDocument40));
//(CLSID_DOMDocument);
if ( NULL == m_XmlDocPtr )
{
return false;
}
m_strRootName = pRootName;
// see if the file exists
if ( !FileExist( pFileName ) ) // if not
{
return false;
}
else // if so
{
try
{
// load it
vbSuccessful = m_XmlDocPtr->load( CComVariant::CComVariant((const char*)pFileName ) );
}
catch (...)
{
vbSuccessful = VARIANT_FALSE;
}
}
if ( VARIANT_TRUE == vbSuccessful )
{
return true; // loaded
}
else
{
return false;
}
}
long CXMLParser::GetNode( const char * pKeyName, IXMLDOMNodePtr& foundNode )
{
int iNumKeys = 0;
std::string* pCStrKeys = NULL;
std::string strBaseKeyName( "//");
strBaseKeyName += pKeyName;
IXMLDOMElementPtr rootElem = NULL;
foundNode = m_XmlDocPtr->selectSingleNode( _com_util::ConvertStringToBSTR(strBaseKeyName.c_str()) );
if ( NULL != foundNode )
{
return 0;
}
else
{
return -1;
}
}
void CXMLParser::GetNodeAttributeData( const IXMLDOMNodePtr PtrNode, map<string,string> &dataMap )
{
IXMLDOMNamedNodeMap *pMapAttrs;
if ( SUCCEEDED(PtrNode->get_attributes(&pMapAttrs)) && (pMapAttrs != NULL))
{
IXMLDOMNodePtr ptrNodeChild;
ptrNodeChild = pMapAttrs->nextNode();
while ( NULL != ptrNodeChild )
{
//
BSTR bstrName;
VARIANT varValue;
string strName;
string strValue;
char cBuffer[_MAX_BUF_SIZE_];
ptrNodeChild->get_nodeName( &bstrName );
ptrNodeChild->get_nodeValue( &varValue );
strName = _com_util::ConvertBSTRToString( bstrName );
SysFreeString( bstrName );
memset( cBuffer, 0x0, sizeof(cBuffer) );
switch ( varValue.vt )
{
case VT_BSTR:
sprintf( cBuffer, "%S", V_BSTR(&varValue) );
cBuffer[_MAX_BUF_SIZE_-1] = 0x0;
break;
case VT_ARRAY:
break;
default:
break;
}
strValue = cBuffer;
dataMap.insert( pair<string,string>(strName, strValue) );
//ptrNodeChild->Release();
ptrNodeChild = pMapAttrs->nextNode();
}
}
}
//////////////////////////////////////////////////////////////////////////
IXMLDOMNodePtr CXMLParser::CreateRootNode( const char * pRootName )
{
IXMLDOMNodePtr pRootNode;
if( NULL != m_XmlDocPtr )
{
m_XmlDocPtr->Release();
m_XmlDocPtr.Detach();
}
if ( NULL == pRootName )
{
return NULL;
}
/* 初始化m_XmlDocPtr */
HRESULT hr = m_XmlDocPtr.CreateInstance( __uuidof(DOMDocument30) );
if ( m_XmlDocPtr == NULL )
{
return NULL;
}
/* 创建根节点元素 */
pRootNode = m_XmlDocPtr->createElement( _bstr_t(pRootName) );
return pRootNode;
}
bool CXMLParser::SaveAsXml( const char * pXmlFileName, IXMLDOMNodePtr PtrRootNode, bool bIsFeedTab )
{
bool bResult = false;
do
{
if ( NULL == PtrRootNode )
{
break;
}
/* 加入头信息 */
IXMLDOMProcessingInstructionPtr pPI = NULL;
pPI = m_XmlDocPtr->createProcessingInstruction( _bstr_t("xml"), _bstr_t("version='1.0' encoding='UTF-8'") );
_variant_t vNullVal;
vNullVal.vt = VT_NULL;
m_XmlDocPtr->insertBefore( pPI, vNullVal );
/* 根节点加入到XML */
m_XmlDocPtr->appendChild( PtrRootNode );
try
{
HRESULT hr = m_XmlDocPtr->save( (_variant_t)pXmlFileName );
if ( !SUCCEEDED(hr) )
{
break;
}
}
catch (...)
{
break;
}
bResult = true;
break;
} while ( 1 );
m_XmlDocPtr.Detach();
return bResult;
}
IXMLDOMNodePtr CXMLParser::CreateSubNode( IXMLDOMNodePtr pParentNode, const char * pSubNodeName )
{
IXMLDOMNodePtr pNewNode ;
pNewNode = m_XmlDocPtr->createElement( _T(pSubNodeName) );
pParentNode->appendChild( pNewNode );
return pNewNode;
}
void CXMLParser::AddNodeAttributes( IXMLDOMNodePtr pNode, const vector<pairType> &vecAttributtes )
{
IXMLDOMElementPtr eptr = pNode;
if ( NULL == pNode )
{
return;
}
vector<pairType>::const_iterator iterBegin = vecAttributtes.begin();
vector<pairType>::const_iterator iterEnd = vecAttributtes.end();
for ( ; iterBegin != iterEnd; iterBegin++ )
{
string strName = iterBegin->first;
string strValue = iterBegin->second;
eptr->setAttribute( _bstr_t(strName.c_str()), _variant_t(strValue.c_str()) );
}
}
void CXMLParser::SetNodeText( IXMLDOMNodePtr pNode, const char * pNodeText )
{
if ( NULL != pNode)
{
pNode->Puttext( _bstr_t(pNodeText) );
}
}
/// protected Implementation
void CXMLParser::Initialize()
{
CoInitialize( NULL );
if( NULL != m_XmlDocPtr )
{
m_XmlDocPtr.Detach();
}
m_XmlDocPtr = NULL;
}
string* CXMLParser::ParseKeys( const char * pFullKeyPath, int &iNumKeys )
{
string cstrTemp;
string* pCStrKeys = NULL;
string strFullKeyPath(pFullKeyPath);
// replace spaces with _ since xml doesn't like them
std::replace(strFullKeyPath.begin(), strFullKeyPath.end(), ' ', '_');
if (*(strFullKeyPath.end() - 1) == '/' )
{
strFullKeyPath.erase(strFullKeyPath.end() -1 );// remove slashes on the end
}
iNumKeys = std::count(strFullKeyPath.begin(), strFullKeyPath.end(), '/') +1;
pCStrKeys = new string[iNumKeys]; // create storage for the keys
if ( pCStrKeys )
{
int iFind = 0, iLastFind = 0, iCount = -1;
// get all of the keys in the chain
while ( iFind != -1 )
{
iFind = strFullKeyPath.find('/', iLastFind);
if ( iFind > -1 )
{
iCount++;
pCStrKeys[iCount].assign(strFullKeyPath, iLastFind, iFind - iLastFind);
iLastFind = iFind + 1;
}
else
{
// make sure we don't just discard the last key in the chain
if ( iLastFind < strFullKeyPath.length() )
{
iCount++;
pCStrKeys[iCount].assign(strFullKeyPath, iLastFind, strFullKeyPath.length() - iLastFind);
}
}
}
}
return pCStrKeys;
}
IXMLDOMNodePtr CXMLParser::FindNode( IXMLDOMNodePtr pParentNode,
string* pCStrKeys, int iNumKeys,
bool bAddNodes )
{
IXMLDOMNodePtr foundNode = NULL;
IXMLDOMElementPtr tempElem = NULL;
for ( int i = 0; i < iNumKeys; i++ )
{
// find the node named X directly under the parent
foundNode = pParentNode->selectSingleNode( _bstr_t(pCStrKeys[i].c_str()) );
if ( NULL == foundNode )
{
// if its not found...
if ( bAddNodes ) // create the node and append to parent (Set only)
{
tempElem = m_XmlDocPtr->createElement( _bstr_t(pCStrKeys[i].c_str()) );
if ( tempElem )
{
foundNode = pParentNode->appendChild( tempElem );
// since we are traversing the nodes, we need to set the parentNode to our foundNode
pParentNode = NULL;
pParentNode = foundNode;