📄 xmlfile.cpp
字号:
// XMLSettings.cpp : implementation file
//
#include "stdafx.h"
#include "xmlfile.h"
#include <algorithm>
/////////////////////////////////////////////////////////////////////////////
// CXMLFile
CXMLFile::CXMLFile()
{
XmlDocPtr = NULL;
xml_file_name = "file.xml";
}
CXMLFile::~CXMLFile()
{
if(XmlDocPtr!=NULL)
XmlDocPtr.Detach();
}
CXMLFile::CXMLFile(const char* filename)
{
::CoInitialize(NULL);
if(XmlDocPtr!=NULL)
XmlDocPtr.Detach();
XmlDocPtr = NULL;
xml_file_name=filename;
load(filename);
}
void CXMLFile::clear()
{
if(XmlDocPtr!=NULL)
XmlDocPtr.Detach();
DeleteFile(xml_file_name.c_str());
load(xml_file_name.c_str());
}
// get a long value
long CXMLFile::GetLong(const char* cstrBaseKeyName, const char* cstrValueName, long lDefaultValue)
{
/*
Since XML is text based and we have no schema, just convert to a string and
call the GetString method.
*/
long lRetVal = lDefaultValue;
char chs[256];
sprintf(chs,"%d", lRetVal);
lRetVal = atol(GetString(cstrBaseKeyName, cstrValueName, chs).c_str() );
return lRetVal;
}
std::string CXMLFile::GetAttribute(const char* cstrBaseKeyName, const char* cstrValueName,
const char* cstrAttributeName, const char* cstrDefaultAttributeValue)
{
std::string strAttributeValue;
std::string strDummy;
GetNodeValue(cstrBaseKeyName, cstrValueName, NULL, strDummy, cstrAttributeName,
cstrDefaultAttributeValue, strAttributeValue);
return strAttributeValue;
}
// get a string value
std::string CXMLFile::GetString(const char* cstrBaseKeyName, const char* cstrValueName, const char* cstrDefaultValue)
{
std::string strValue;
std::string strDummy;
GetNodeValue(cstrBaseKeyName, cstrValueName, cstrDefaultValue, strValue,
NULL, NULL, strDummy);
return strValue;
}
// set a long value
long CXMLFile::SetLong(const char* cstrBaseKeyName, const char* cstrValueName, long lValue)
{
long lRetVal = 0;
char chsVal[256];
sprintf(chsVal,"%d", lValue);
lRetVal = SetString(cstrBaseKeyName, cstrValueName, chsVal);
return lRetVal;
}
// set a string value
long CXMLFile::SetString(const char* cstrBaseKeyName, const char* cstrValueName, const char* cstrValue)
{
return SetNodeValue(cstrBaseKeyName, cstrValueName,cstrValue);
}
// set a string Attribute
long CXMLFile::SetAttribute(const char* cstrBaseKeyName, const char* cstrValueName,
const char* cstrAttributeName, const char* cstrAttributeValue)
{
return SetNodeValue(cstrBaseKeyName, cstrValueName, NULL, cstrAttributeName, cstrAttributeValue);
}
long CXMLFile::GetNodeValue(const char* cstrBaseKeyName, const char* cstrValueName,
const char* cstrDefaultValue, std::string& strValue, const char* cstrAttributeName,
const char* cstrDefaultAttributeValue,std::string& strAttributeValue)
{
int iNumKeys = 0;
std::string cstrValue = cstrDefaultValue;
std::string* pCStrKeys = NULL;
std::string strBaseKeyName("//");
strBaseKeyName +=cstrBaseKeyName;
if( strBaseKeyName.at(strBaseKeyName.length() -1) !='/' )
strBaseKeyName += "/";
strBaseKeyName += cstrValueName;
MSXML2::IXMLDOMElementPtr rootElem = NULL;
MSXML2::IXMLDOMNodePtr foundNode = NULL;
foundNode=XmlDocPtr->selectSingleNode( _com_util::ConvertStringToBSTR(strBaseKeyName.c_str()) );
if (foundNode)
{
// get the text of the node (will be the value we requested)
BSTR bstr = NULL;
HRESULT hr = foundNode->get_text(&bstr);
strValue =_com_util::ConvertBSTRToString(bstr);
if(cstrAttributeName!=NULL)
{
MSXML2::IXMLDOMElementPtr elptr=foundNode;
strAttributeValue=_com_util::ConvertBSTRToString(
_bstr_t( elptr->getAttribute(_bstr_t(cstrAttributeName)) )
);
}
if (bstr)
{
SysFreeString(bstr);
bstr = NULL;
}
return 0;
}
else
return -1;
}
long CXMLFile::SetNodeValue(const char* cstrBaseKeyName, const char* cstrValueName,
const char* cstrValue, const char* cstrAttributeName, const char* cstrAttributeValue)
{
/* RETURN VALUES:
0 = SUCCESS -1 = LOAD FAILED -2 = NODE NOT FOUND
-3 = PUT TEXT FAILED -4 = SAVE FAILED
*/
long lRetVal = 0;
int iNumKeys = 0;
std::string* pCStrKeys = NULL;
// Add the value to the base key separated by a '\'
std::string strBaseKeyName(cstrBaseKeyName);
if( strBaseKeyName.at(strBaseKeyName.length() -1) !='/' )
strBaseKeyName += "/";
strBaseKeyName += cstrValueName;
// Parse all keys from the base key name (keys separated by a '\')
pCStrKeys = ParseKeys(strBaseKeyName.c_str(), iNumKeys);
// Traverse the xml using the keys parsed from the base key name to find the correct node
if (pCStrKeys)
{
if (XmlDocPtr == NULL)
return -2;
MSXML2::IXMLDOMElementPtr rootElem = NULL;
MSXML2::IXMLDOMNodePtr foundNode = NULL;
XmlDocPtr->get_documentElement(&rootElem); // root node
if (rootElem)
{
// returns the last node in the chain
foundNode = FindNode(rootElem, pCStrKeys, iNumKeys, true);
if (foundNode)
{
HRESULT hr;
// set the text of the node (will be the value we sent)
if(cstrValue!=NULL)
hr = foundNode->put_text(_bstr_t(cstrValue));
if(cstrAttributeName!=NULL )
{
MSXML2::IXMLDOMElementPtr elptr=foundNode;
elptr->setAttribute(_bstr_t(cstrAttributeName),
_bstr_t(cstrAttributeValue) );
}
if (!SUCCEEDED(hr))
lRetVal = -3;
foundNode = NULL;
}
else
lRetVal = -2;
rootElem = NULL;
}
delete [] pCStrKeys;
}
return lRetVal;
}
// xmlfile.DeleteSetting("Settings/who","");删除该键及其所有子键
// delete a key or chain of keys
long CXMLFile::DeleteSetting(const char* cstrBaseKeyName, const char* cstrValueName)
{
long bRetVal = -1;
int iNumKeys = 0;
std::string* pCStrKeys = NULL;
std::string strBaseKeyName(cstrBaseKeyName);
if ( strBaseKeyName!="" )
{
if( strBaseKeyName.at(strBaseKeyName.length() -1) !='/' )
strBaseKeyName += "/";
strBaseKeyName += std::string(cstrValueName);
}
// Parse all keys from the base key name (keys separated by a '\')
pCStrKeys = ParseKeys(strBaseKeyName.c_str(), iNumKeys);
// Traverse the xml using the keys parsed from the base key name to find the correct node.
if (pCStrKeys)
{
if (XmlDocPtr == NULL)
return bRetVal;
MSXML2::IXMLDOMElementPtr rootElem = NULL;
MSXML2::IXMLDOMNodePtr foundNode = NULL;
XmlDocPtr->get_documentElement(&rootElem); // root node
if (rootElem)
{
// returns the last node in the chain
foundNode = FindNode(rootElem, pCStrKeys, iNumKeys);
if (foundNode)
{
// get the parent of the found node and use removeChild to delete the found node
MSXML2::IXMLDOMNodePtr parentNode = NULL;
foundNode->get_parentNode(&parentNode);
if (parentNode)
{
HRESULT hr = parentNode->removeChild(foundNode);
parentNode = NULL;
}
foundNode = NULL;
}
rootElem = NULL;
}
delete [] pCStrKeys;
}
return bRetVal;
}
// get a basekey's all children's value
long CXMLFile::GetKeysValue(const char* cstrBaseKeyName, std::map<std::string, std::string>& keys_val)
{
int iNumKeys = 0;
std::string* pCStrKeys = NULL;
std::string strValue;
pCStrKeys = ParseKeys(cstrBaseKeyName, iNumKeys);
if (pCStrKeys)
{
if (XmlDocPtr == NULL) // load the xml document
return -1;
MSXML2::IXMLDOMElementPtr rootElem = NULL;
MSXML2::IXMLDOMNodePtr foundNode = NULL;
MSXML2::IXMLDOMNodeListPtr nodelst= NULL;
MSXML2::IXMLDOMNodePtr pNode= NULL;
XmlDocPtr->get_documentElement(&rootElem); // root node
if (rootElem)
{
foundNode = FindNode(rootElem, pCStrKeys, iNumKeys);
if (foundNode)
nodelst=foundNode->GetchildNodes();
if(nodelst!=NULL)
{
for (int i=0; i<nodelst->length; i++)
{
pNode = nodelst->item[i];
keys_val[(const char*)(pNode->nodeName)]=pNode->text;//(const char*)pNode->xml;
}
foundNode = NULL;
}
pNode=NULL;
nodelst= NULL;
foundNode = NULL;
rootElem = NULL;
}
delete [] pCStrKeys;
}
return 0;
/*
std::map<std::string, std::string> mp;
std::map<std::string, std::string>::const_iterator iter;
std::string strmsg;
xmlfile.GetKeysValue("xmlRoot/西安/空军工程大学/学生/入学新生", mp);
for(iter=mp.begin(); iter!=mp.end(); ++iter)
{
strmsg+=" ("+iter->first+", "+ iter->second+") \n";
}
AfxMessageBox(strmsg.c_str());
*/
}
// get a basekey's all children's value
long CXMLFile::GetKeys(const char* cstrBaseKeyName, std::vector<std::string>& keys)
{
int iNumKeys = 0;
std::string* pCStrKeys = NULL;
std::string strValue;
pCStrKeys = ParseKeys(cstrBaseKeyName, iNumKeys);
if (pCStrKeys)
{
if (XmlDocPtr == NULL) // load the xml document
return -1;
MSXML2::IXMLDOMElementPtr rootElem = NULL;
MSXML2::IXMLDOMNodePtr foundNode = NULL;
MSXML2::IXMLDOMNodePtr pNode= NULL;
XmlDocPtr->get_documentElement(&rootElem); // root node
if (rootElem)
{
foundNode = FindNode(rootElem, pCStrKeys, iNumKeys);
pNode=foundNode->GetfirstChild();
while(pNode!=NULL)
{
//pNode =pNode-> nodelst->item[i];
keys.push_back ((const char*)pNode->nodeName);//(const char*)pNode->xml;
//ATLTRACE((const char*)pNode->text);ATLTRACE("\n==============");
pNode=pNode->GetnextSibling();
}
}
delete [] pCStrKeys;
}
return 0;
}
long CXMLFile::GetRootElem(MSXML2::IXMLDOMElementPtr rootElem)
{
return XmlDocPtr->get_documentElement(&rootElem);
}
long CXMLFile::GetNode(const char* cstrKeyName,
MSXML2::IXMLDOMNodePtr& foundNode)
{
int iNumKeys = 0;
std::string* pCStrKeys = NULL;
std::string strBaseKeyName( "//");
strBaseKeyName +=cstrKeyName;
MSXML2::IXMLDOMElementPtr rootElem = NULL;
foundNode=XmlDocPtr->selectSingleNode( _com_util::ConvertStringToBSTR(strBaseKeyName.c_str()) );
if (foundNode)
{
return 0;
}
else
return -1;
}
// Parse all keys from the base key name.
std::string* CXMLFile::ParseKeys(const char* cstrFullKeyPath, int &iNumKeys)
{
std::string cstrTemp;
std::string* pCStrKeys = NULL;
std::string strFullKeyPath(cstrFullKeyPath);
// 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 std::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;
}
//if the specific file exist, then return true, else return false
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 (hFile != INVALID_HANDLE_VALUE)
{
// If the handle is valid then the file exists.
CloseHandle(hFile);
bExist = true;
}
}
return (bExist);
}
// load the XML file into the parser
bool CXMLFile::load(const char* filename, const char* root_name)
{
if(XmlDocPtr != NULL)
return false;
VARIANT_BOOL vbSuccessful;
xml_file_name=filename;
// initialize the Xml parser
HRESULT hr = XmlDocPtr.CreateInstance(__uuidof(MSXML2::DOMDocument30));
//__uuidof(MSXML2::DOMDocument40));
//(MSXML2::CLSID_DOMDocument);
if (XmlDocPtr == NULL) return false;
m_root_name=root_name;
// see if the file exists
if ( !FileExist(filename ) ) // if not
{
// create it
std::string strtmp("<?xml version=\"1.0\" ?><");//encoding=\"UTF-16\"
if(root_name!=NULL)
{
strtmp+=root_name;
strtmp+="></";
strtmp+=root_name;
strtmp+=">";
}
else
strtmp+="xmlRoot></xmlRoot>";
vbSuccessful=XmlDocPtr->loadXML(_bstr_t(strtmp.c_str()));
}
else // if so
{
// load it
vbSuccessful=XmlDocPtr->load(CComVariant::CComVariant((const char*)filename ));
}
if (vbSuccessful == VARIANT_TRUE)
{
return true; // loaded
}
else
{
// an XML load error occurred so display the reason
MSXML2::IXMLDOMParseErrorPtr pIParseError = NULL;
XmlDocPtr->get_parseError(&pIParseError);
if (pIParseError)
{
long value;
BSTR bstr = NULL;
HRESULT hr = pIParseError->get_errorCode(&value);
pIParseError->get_reason(&bstr);
//std::string cstrMessage=(char *)_bstr_t(bstr, true);
MessageBox( NULL, (char *)_bstr_t(bstr, true), "错误提示",
MB_OK|MB_ICONERROR);
if (bstr) { SysFreeString(bstr); bstr = NULL; }
pIParseError = NULL;
}
return false;
}
}
// save the XML file
bool CXMLFile::save(const char* filename)
{
if(XmlDocPtr==NULL)
return false;
HRESULT hr;
if(filename==NULL||filename=="")
hr = XmlDocPtr->save(CComVariant::CComVariant(xml_file_name.c_str()));
else
hr = XmlDocPtr->save(CComVariant::CComVariant(filename));
// xml_file_name=filename;
//XmlDocPtr=NULL;
return SUCCEEDED(hr);
}
// discard any changes
void CXMLFile::DiscardChanges()
{
XmlDocPtr=NULL;
}
// find a node given a chain of key names
MSXML2::IXMLDOMNodePtr CXMLFile::FindNode(MSXML2::IXMLDOMNodePtr parentNode,
std::string* pCStrKeys, int iNumKeys,
bool bAddNodes /*= false*/)
{
MSXML2::IXMLDOMNodePtr foundNode = NULL;
MSXML2::IXMLDOMElementPtr tempElem = NULL;
for (int i=0; i<iNumKeys; i++)
{
// find the node named X directly under the parent
foundNode = parentNode->selectSingleNode(_bstr_t(pCStrKeys[i].c_str()));
if (foundNode == NULL)
{
// if its not found...
if (bAddNodes) // create the node and append to parent (Set only)
{
tempElem=XmlDocPtr->createElement(_bstr_t(pCStrKeys[i].c_str()));
if (tempElem)
{
foundNode=parentNode->appendChild(tempElem);
// since we are traversing the nodes, we need to set the parentNode to our foundNode
parentNode = NULL;
parentNode = foundNode;
foundNode = NULL;
}
}
else
{
foundNode = NULL;
parentNode = NULL;
break;
}
}
else
{
parentNode = NULL;
parentNode = foundNode;
foundNode = NULL;
}
}
return parentNode;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -