📄 xmlparse.cpp
字号:
// CXMLParse.cpp: implementation of the CXMLParse class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "XMLParse.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define XML_SUCCEEDED() SUCCEEDED(m_hResult)
#define XML_FAILED() FAILED(m_hResult)
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CXMLParse::CXMLParse()
{
ResetVariable();
}
CXMLParse::~CXMLParse()
{
FreeAllResource();
}
//
// 在内存中构造DOM树,自动创建处理指令(声明)节点<?xml version="1.0"
// encoding="UTF-8"?>,并根据指定的根元素名称创建跟元素节点.
// 可以在声明节点后加入注释,不支持DTD节点创建.
//
BOOL CXMLParse::CreateNewXMLDOM(
LPCTSTR strTopElementName, // 根元素名
LPCTSTR strComment/*=""*/, // 注释
LPCTSTR strEncoding/*="UTF-8"*/ // 编码
)
{
//初始化
ResetVariable ();
//创建COM对象实例
m_hResult = CoCreateInstance(CLSID_DOMDocument40,
NULL,
CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument2,
(void**)&m_pXMLDOMDoc);
if ( XML_FAILED() ) // 如果COM对象实例创建失败
{
AfxMessageBox ( "Create COM object instance failed" );
OutErrorStr ();
ResetNodePtr ( &m_pXMLDOMDoc );
return FALSE;
}
// 创建处理指令(声明)节点
BSTR target = _com_util::ConvertStringToBSTR("xml");
CString csHead;
csHead.Format ( "version=\"1.0\" encoding=\"%s\"", strEncoding );
BSTR data = csHead.AllocSysString();
IXMLDOMProcessingInstruction *pi;
m_hResult = m_pXMLDOMDoc->createProcessingInstruction ( target, data, &pi );
if ( XML_FAILED() ) // 创建处理指令(声明)节点失败
{
//释放内存中COM对象实例
ResetNodePtr ( &m_pXMLDOMDoc );
AfxMessageBox ( "Create node failed" );
return FALSE;
}
// 处理指令(声明)节点插入DOM树
IXMLDOMNode * pTempNode = NULL;
VARIANT vtTemp;
vtTemp.vt= VT_EMPTY;
m_hResult = m_pXMLDOMDoc->insertBefore ( pi, vtTemp, &pTempNode );
if ( XML_FAILED() ) // 处理指令(声明)节点插入DOM树失败
{
//释放内存中COM对象实例
ResetNodePtr ( &pTempNode );
ResetNodePtr ( &m_pXMLDOMDoc );
AfxMessageBox ( "Create DOMTree failed" );
return FALSE;
}
HRESULT hrErr1,hrErr2,hrErr3,hrErr4;
// 创建注释节点
IXMLDOMComment * pTempComment = NULL;
BSTR tempComment = _com_util::ConvertStringToBSTR(strComment);
hrErr1 = m_pXMLDOMDoc->createComment ( tempComment, &pTempComment );
// 插入注释节点到DOM树
ResetNodePtr ( &pTempNode );
vtTemp.vt= VT_EMPTY;
hrErr2 = m_pXMLDOMDoc->insertBefore ( pTempComment, vtTemp, &pTempNode);
ResetNodePtr ( &pTempComment );
//创建顶层元素节点
IXMLDOMElement * pTempElement = NULL;
BSTR tempElementName = _com_util::ConvertStringToBSTR ( strTopElementName );
hrErr3 = m_pXMLDOMDoc->createElement ( tempElementName, &pTempElement );
//插入顶层元素节点到DOM树
pTempNode = NULL;
vtTemp.vt= VT_EMPTY;
hrErr4 = m_pXMLDOMDoc->insertBefore ( pTempElement, vtTemp, &pTempNode );
ResetNodePtr ( &pTempElement );
if ( (hrErr1 == S_OK) && (hrErr2 == S_OK) && (hrErr3 == S_OK) && (hrErr4 == S_OK) )
{
IXMLDOMElement * pTopElement = NULL;
m_pXMLDOMDoc->get_documentElement ( &pTopElement );
//m_pCurNodeList赋值
m_pXMLDOMDoc->selectNodes(_com_util::ConvertStringToBSTR("*"),
&m_pCurNodeList);
//m_pCurNode 指向根元素节点
//m_nCurNodeListLength为1
//m_nCurNodeNumber为0
if (m_pCurNodeList != NULL)
{
m_pCurNodeList->get_length(&m_nCurNodeListLength);
m_nCurNodeNumber = 0;
m_pCurNodeList->get_item(m_nCurNodeNumber,&m_pCurNode);
}
//释放临时对象
ResetNodePtr ( &pTopElement );
}
else
{
//释放内存中COM对象实例
ResetNodePtr ( &m_pXMLDOMDoc );
AfxMessageBox ( "Create or insert node failed" );
return FALSE;
}
m_pRootNode = m_pCurNode;
return TRUE;
}
void CXMLParse::OutErrorStr()
{
CString csMsg;
_com_error er( m_hResult );
csMsg.Format ( "MSXML error : %s\n", er.ErrorMessage() );
AfxMessageBox ( csMsg );
}
//
// 将私有变量重设
//
void CXMLParse::ResetVariable()
{
m_pXMLDOMDoc = NULL;
m_pCurNodeList = NULL;
m_nCurNodeListLength = 0;
m_nCurNodeNumber = 0;
m_pCurNode = NULL;
m_hResult = S_OK;
m_pRootNode = NULL;
m_dwTotalElementNum = 0;
}
void CXMLParse::FreeAllResource()
{
ResetNodePtr ( &m_pCurNode );
ResetNodePtr ( &m_pCurNodeList );
ResetNodePtr ( &m_pXMLDOMDoc );
ResetVariable();
}
/**************************************************************************
* 函数介绍:将内存中的DOM树内容保存到指定XML文件中.
*
* 输入参数:strDestinationFile:要写入的XML文件的完整路径名.
* 返回值 :TRUE - 成功
* FALSE - 失败
***************************************************************************/
BOOL CXMLParse::Save(LPCTSTR strDestinationFile)
{
VARIANT varDestinationFile;
varDestinationFile.vt = VT_BSTR;
varDestinationFile.bstrVal = _com_util::ConvertStringToBSTR(strDestinationFile);
m_hResult = m_pXMLDOMDoc->save(varDestinationFile);
if ( XML_FAILED() )
{
OutErrorStr();
return FALSE;
}
return TRUE;
}
/**************************************************************************
* 函数介绍:指定XML源文件,在内存中构造DOM树,
* 并读取指定XML文件的内容到DOM树中.如果出错则把COM对象实例(DOM树)
* 释放并且指向DOM树的指针赋空.
* 如果XML文件读取正确
* m_pCurNodeList包含一个节点即根元素节点
* m_pCurNode指向根元素节点
* m_nCurNodeListLength为1
* m_nCurNodeNumber为0
*
* 输入参数:lpszFileOrData - 要读取的XML文件的完整路径名,或者是 XML 字符串
**************************************************************************/
BOOL CXMLParse::Load(LPCTSTR lpszFileOrData, BOOL bIsFileName/*=TRUE*/)
{
if ( !lpszFileOrData || strlen(lpszFileOrData) < 1 ) return FALSE;
//初始化
ResetVariable ();
//创建COM对象实例
m_hResult = CoCreateInstance(CLSID_DOMDocument40,
NULL,
CLSCTX_INPROC_SERVER,
IID_IXMLDOMDocument2,
(void**)&m_pXMLDOMDoc);
// 如果COM对象实例创建失败
if ( XML_FAILED() )
{
AfxMessageBox ( "Create COM object instance failed" );
OutErrorStr ();
ResetNodePtr ( &m_pXMLDOMDoc );
return FALSE;
}
// 读取XML文档内容到内存中DOM树
VARIANT_BOOL *bLoadSuccess = NULL;
if ( bIsFileName )
{
VARIANT varSourceFile;
varSourceFile.vt = VT_BSTR;
varSourceFile.bstrVal = _com_util::ConvertStringToBSTR(lpszFileOrData);
//读取源文件
//如果有DTD则也进行有效性检查,否则不进行有效性检查
m_hResult = m_pXMLDOMDoc->load(varSourceFile, bLoadSuccess);
}
else
{
m_hResult = m_pXMLDOMDoc->loadXML ( _com_util::ConvertStringToBSTR(lpszFileOrData), bLoadSuccess );
}
// 如果XML文件读取错误(包括良构和有效性检查错误)
if ( XML_FAILED() )
{
//释放内存中COM对象实例
ResetNodePtr ( &m_pXMLDOMDoc );
AfxMessageBox ( "Read XML file failed or file structure invalid" );
return FALSE;
}
//如果XML文件读取正确
//m_pCurNodeList包含一个节点即根元素节点
//m_pCurNode指向根元素节点
//m_nCurNodeListLength为1
//m_nCurNodeNumber为0
IXMLDOMElement * pTopElement = NULL;
m_pXMLDOMDoc->get_documentElement(&pTopElement);
ResetNodePtr ( &pTopElement );
//m_pCurNodeList赋值
m_pXMLDOMDoc->selectNodes(_com_util::ConvertStringToBSTR("*"),
&m_pCurNodeList);
//m_pCurNode指向根元素节点
//m_nCurNodeListLength为1
//m_nCurNodeNumber为0
if ( m_pCurNodeList != NULL )
{
m_pCurNodeList->get_length(&m_nCurNodeListLength);
m_nCurNodeNumber = 0;
m_pCurNodeList->get_item(m_nCurNodeNumber,&m_pCurNode);
}
m_pRootNode = m_pCurNode;
return ( m_pRootNode != NULL );
}
/**************************************************************************
* 函数介绍:在当前元素节点层次中变换当前元素节点.在同一节点链表中跳转
* 如果执行成功,使m_pCurNode指向当前元素节点链表中的指定位置,
* m_nCurNodeNumber为当前元素节点在当前元素节点链表中的位置.
*
* 输入参数:curNodeNumber: int类型,指定要选中的元素节点在当前元素节点链
* 表中的位置.
* 返回值: FALSE - 指定的位置越界或者其它执行错误.
* TRUE: - 执行成功.
**************************************************************************/
BOOL CXMLParse::GoTo_ParallelNode(long curNodeNumber)
{
//判断指定的当前元素节点的位置是否越界
if ((curNodeNumber >= 0) && (curNodeNumber < m_nCurNodeListLength))
{
m_nCurNodeNumber = curNodeNumber;
m_hResult = m_pCurNodeList->get_item(m_nCurNodeNumber, &m_pCurNode);
if ( XML_SUCCEEDED() )
return TRUE;
}
TRACE ( "Invalid function parameter or node position is wrong\n" );
return FALSE;
}
/**************************************************************************
* 函数介绍:向下变换当前元素节点层次.进入子节点
* 如果当前元素节点有子元素节点m_pCurNodeList和
* m_nCurNodeListLength赋相应值,m_nCurNodeNumber为0,m_pCurNode指
* 向新节点链表的第一个节点.
* 如果当前元素节点没有子元素节点,保持m_pCurNodeList,
* m_nCurNodeListLength,m_nCurNodeNumber,m_pCurNode值不变.
*
* 返回值 :FALSE: 如果当前元素节点没有子元素节点或者其它执行错误
* TRUE: 如果当前元素节点有子元素节点
**************************************************************************/
BOOL CXMLParse::GoTo_Child()
{
IXMLDOMNodeList *pTempNodeList = NULL;
m_pCurNode->selectNodes(_com_util::ConvertStringToBSTR("*"),&pTempNodeList);
//判断当前元素节点是否有子元素节点
if (pTempNodeList != NULL)
{
m_pCurNode->selectNodes(_com_util::ConvertStringToBSTR("*"),&m_pCurNodeList);
m_pCurNodeList->get_length(&m_nCurNodeListLength);
m_nCurNodeNumber = 0;
if (m_nCurNodeListLength > 0)
{
m_pCurNodeList->get_item(0,&m_pCurNode);
}
ResetNodePtr ( &pTempNodeList );
return TRUE;
}
TRACE ( "Goto child node failed\n" );
return FALSE;
}
//
// 由于 m_pCurNode 改变,所以需要更新其他当前变量 m_pCurNodeList,
// m_nCurNodeNumber,m_nCurNodeListLength 的值
//
void CXMLParse::UpdateCurValue ()
{
IXMLDOMNode * pTempNode = NULL;
m_pCurNode->get_parentNode ( &pTempNode );
pTempNode->selectNodes(_com_util::ConvertStringToBSTR("*"),&m_pCurNodeList);
ResetNodePtr ( &pTempNode );
}
/**************************************************************************
* 函数介绍:向上变换当前元素节点层次.退回到父节点
* 如果当前元素节点不是顶层元素节点m_pCurNodeList和
* m_nCurNodeListLength赋相应值,m_nCurNodeNumber为0,m_pCurNode指
* 向新节点链表的第一个节点.
* 如果当前元素节点是顶层元素节点,保持m_pCurNodeList,
* m_nCurNodeListLength,m_nCurNodeNumber,m_pCurNode值不变.
*
* 返回值 :FALSE: 如果当前元素节点是顶层元素节点或者其它执行错误
* TRUE: 如果当前元素节点不是顶层元素节点
**************************************************************************/
BOOL CXMLParse::GoTo_Parent()
{
// 取当前元素节点的父节点
// 通过其父节点的类型判断当前元素节点是否为根元素节点
IXMLDOMNode * pTempNode = NULL;
m_pCurNode->get_parentNode ( &pTempNode );
if ( pTempNode != NULL )
{
BSTR bszTemp;
CString strTemp;
pTempNode->get_nodeTypeString ( &bszTemp );
strTemp = CString(bszTemp);
//如果当前元素节点不是根元素节点
if ( strTemp.Compare("document") != 0 )
{
m_pCurNode = pTempNode;
m_pCurNode->get_parentNode ( &pTempNode );
pTempNode->selectNodes(_com_util::ConvertStringToBSTR("*"),&m_pCurNodeList);
m_pCurNodeList->get_length(&m_nCurNodeListLength);
m_nCurNodeNumber = 0;
if (m_nCurNodeListLength > 0)
{
m_pCurNodeList->get_item(0,&m_pCurNode);
ResetNodePtr ( &pTempNode );
return TRUE;
}
}
}
ResetNodePtr ( &pTempNode );
return FALSE;
}
/**************************************************************************
* 函数介绍:退回到根点
* 如果当前元素节点不是顶层元素节点 m_pCurNodeList 和
* m_nCurNodeListLength赋相应值,m_nCurNodeNumber 为0, m_pCurNod e指
* 向新节点链表的第一个节点.
* 如果当前元素节点是顶层元素节点,保持 m_pCurNodeList,
* m_nCurNodeListLength ,m_nCurNodeNumber,m_pCurNode值不变.
*
* 返回值 :FALSE: 如果当前元素节点是顶层元素节点或者其它执行错误
* TRUE: 如果当前元素节点不是顶层元素节点
**************************************************************************/
BOOL CXMLParse::GoTo_Root()
{
if ( !m_pRootNode )
return FALSE;
m_pCurNode = m_pRootNode;
UpdateCurValue ();
return TRUE;
}
/**************************************************************************
* 函数介绍:根据标签名跳转
* 如果找到标签对应的元素,节点m_pCurNodeList和
* m_nCurNodeListLength 赋相应值,m_nCurNodeNumber 为0,m_pCurNode指
* 向新节点链表的第一个节点.
* 如果找不到标签对应的元素,保持m_pCurNodeList,
* m_nCurNodeListLength,m_nCurNodeNumber,m_pCurNode值不变.
*
* 返回值 :FALSE: 如果当前元素节点是顶层元素节点或者其它执行错误
* TRUE: 如果当前元素节点不是顶层元素节点
**************************************************************************/
BOOL CXMLParse::GoTo_TagName(LPCTSTR lpszTagName)
{
IXMLDOMNodeList *pTempNodeList = NULL;
m_hResult = m_pXMLDOMDoc->getElementsByTagName (
_com_util::ConvertStringToBSTR(lpszTagName),
&pTempNodeList );
CString csMsg;
if ( XML_FAILED() )
{
csMsg.Format ( "Could not find specify tag : [ %s ]", lpszTagName );
AfxMessageBox ( csMsg );
return FALSE;
}
IXMLDOMNode *pTempNode = NULL;
m_hResult = pTempNodeList->get_item ( 0, &pTempNode );
if ( XML_FAILED() || !pTempNode )
{
csMsg.Format ( "Get item failed. Tag name is : [ %s ]", lpszTagName );
TRACE ( "%s\n", csMsg );
return FALSE;
}
m_pCurNode = pTempNode;
UpdateCurValue ();
return TRUE;
}
/**************************************************************************
* 函数介绍:删除当前元素节点的指定属性.
*
* 输入参数:strAttributeName: CString类型,指明当前元素节点指定属性的名称.
* 返回值 :1:执行成功.
* 2:执行失败.
**************************************************************************/
BOOL CXMLParse::DelAttribute(LPCTSTR strAttributeName)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -