My FAQ,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > Visual C++ > XML
利用XML文件写日志的类
作者:未知 时间:2005-07-20 14:21 出处:VC知识库 责编:MyFAQ
              摘要:利用XML文件写日志的类

利用XML文件写日志的类
作者:战鹰

下载本文示例工程

对于程序执行期间的错误跟踪!相信大家都有自己的一套办法!!!但都是利用文件文件,我这次利用的是XML&XSL,可产生报表格式的日志,轻松生成报表!!!

我参考了Emilio Guijarro Cameros的CXMLProfile写XML配置文件的思想!!!利用XML 接口IXMLDOMDocument 、IXMLDOMNode 、IXMLDOMElement和 MFC相结合,写成了一个CXMLLogfile类,只暴露了两个公共方法

void Log(LPCTSTR lpszFilName,LPCTSTR s,...);
bool ClearAll()
Log是添加一条日志,ClearAll是清除所有日志!!!当大家需要查看日值时,只需要打开相应的XML文件Log.XML就可以看到一个日志表格了,为此我专门写了一个XSL样式文件(XML样式XSL文件必须在XML文件同一目录下)!
XSL样式文件代码:
<?xml version="1.0" encoding="GB2312"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">

<html>
 <head>
  <title><xsl:value-of select="LogFile/AppName" /> 日志文件</title>
 </head>
 <body>
  <h1><xsl:value-of select="LogFile/AppName" /> 运行日志文件</h1>

  <table border="0" cellspacing="1" cellpadding="0">
   <tr>
    <td bgcolor="#dddddd">
     <table border="0" cellpadding="3" cellspacing="1">
      <tr>
       <td bgcolor="#ffffff"> </td>
       <td width="140" valign="center" bgcolor="#ffffff"><b>日期-时间</b></td>
       <td bgcolor="#ffffff"><b>错误信息</b></td>
       <td bgcolor="#ffffff"><b>具体位置信息</b></td>
      </tr>

      <xsl:for-each select="LogFile/LogItem">
       <tr onMouseover="">
        <td bgcolor="#ffffff" valign="top"><xsl:number count="LogItem" />.</td>
        <td bgcolor="#ffffff" valign="top"><nobr><xsl:value-of select="Date" /></nobr><xsl:value-of select="Time" /></td>
        <td bgcolor="#ffffff" valign="top"><xsl:value-of select="comment" /></td>
        <td bgcolor="#ffffff" valign="top"><xsl:value-of select="Filename" /></td>
       </tr>
      </xsl:for-each>
     </table>
    </td>
   </tr>
  </table>

  <font style="font-size:5.0mm;"><br/>
  Log.xsl by force eagle <<a href="mailto:force_eagle@163.net">force_eagle@163.net</a>></font>

 </body>
</html>

</xsl:template>
</xsl:stylesheet>
以下是一日志表格图:


以下是源代码,需要IE5.5以上支持!!!如果编译错误!请下载微软的最新XML SDK!!!!
// XMLLogfile.h: interface for the CXMLLogfile class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_XMLLOGFILE_H__EA8ACC84_7139_49F6_9B8A_F69D9CF5C385__INCLUDED_)
#define AFX_XMLLOGFILE_H__EA8ACC84_7139_49F6_9B8A_F69D9CF5C385__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <sys/timeb.h>
#include <time.h>
#include <atlbase.h>
#include <msxml.h>
#include <shlobj.h>
#include <comdef.h>
//Author : By force eagle
//Date time : 2003-5-26 17:08
//reference : 
//				CXMLProfile By Emilio Guijarro Cameros 
//				Christian Richardt

#pragma comment(lib,"msxml2.lib")
class CXMLLogfile : public CObject  
{
	CString m_strFileName;
	IXMLDOMDocument *m_pXMLDoc;
	
	IXMLDOMNode * GetChildNode(LPCTSTR lpszParent, LPCTSTR lpszChild,BOOL bCreate = TRUE);
	IXMLDOMNode * GetFirstLevelNode(LPCTSTR lpszNodeName,BOOL bCreate = TRUE);

	// UNIX timestamp: seconds from 1970-01-01 00:00:00 (UTC)
	inline double TimeStamp(void)
	{
		_timeb ts;
		_ftime( &ts );
		return (int)ts.time + (ts.millitm/1000.0);
	};
protected:
	void AppendNode(IXMLDOMNode * pXMLItem, LPCTSTR lpszNodeName, LPCTSTR lpszValue);
	void AppendItem(LPCTSTR lpszFileName,LPCTSTR lpszComment);

	void Flush();

	bool CreateLogFile(LPCTSTR lpszLogFilName);

	void DumpComError(_com_error &e);

	void Init();


public:
	CXMLLogfile(LPCTSTR lpszFileName = NULL);
	virtual ~CXMLLogfile();
	void Log(LPCTSTR lpszFilName,LPCTSTR s,...);
	bool ClearAll();
};

#endif // !defined(AFX_XMLLOGFILE_H__EA8ACC84_7139_49F6_9B8A_F69D9CF5C385__INCLUDED_)
// XMLLogfile.cpp: implementation of the CXMLLogfile class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "XMLLogfile.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/*
static TCHAR *szLogOrig= {_T("<?xml version=\"1.0\" encoding=\"GB2312\"?>\n"
	"<?xml-stylesheet href=\"Log.xsl\" type=\"text/xsl\"?>\n"
	"<LogFile>\n<AppName>XXXX</AppName>\n<Timestamp>1053925276.381</Timestamp>\n"
	"<Date>2003-05-26</Date>\n<Time>13:01:16.861</Time>\n</LogFile>\n")};
//*/
static WCHAR *wszLogOrig = {L"<?xml version=\"1.0\" encoding=\"GB2312\"?>\n<?xml-stylesheet href=\"Log.xsl\" type=\"text/xsl\"?>\n<LogFile>\n<AppName>XXXX</AppName>\n<Timestamp>1053925276.381</Timestamp>\n<Date>2003-05-26</Date>\n<Time>13:01:16.861</Time>\n</LogFile>\n"};

CXMLLogfile::CXMLLogfile(LPCTSTR lpszFileName)
{
	VARIANT_BOOL bResult;
	IXMLDOMElement *pRootNode;
	HRESULT hr;
	if (NULL == lpszFileName)
	{
		CString strHlpPath ,strAppName;
		strHlpPath = AfxGetApp()->m_pszHelpFilePath;
		strAppName = AfxGetAppName();
		strHlpPath = strHlpPath.Left(strHlpPath.GetLength() - 4
			- strAppName.GetLength());
		m_strFileName = strHlpPath + _T("LOG.XML");
	}
	else
	{
		m_strFileName = lpszFileName;
	}

	hr = CoInitialize(NULL); 
LoadLog:
	if(SUCCEEDED(hr)) 
	{
		hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, 
			IID_IXMLDOMDocument, (void**)&m_pXMLDoc);
		if(SUCCEEDED(hr)) 
		{
			m_pXMLDoc->load(COleVariant(m_strFileName), &bResult);
		}
	}

	//取得根节点
	m_pXMLDoc->get_documentElement(&pRootNode);

	if(pRootNode == NULL)	//无根节点
	{
		m_pXMLDoc->Release();
		m_pXMLDoc = NULL;
		//重新创建XML日值文件
		CreateLogFile(m_strFileName);
		goto LoadLog; //重新载入
	}
	else
	{
		Init();
	}
}

CXMLLogfile::~CXMLLogfile()
{
	m_pXMLDoc->save(COleVariant(m_strFileName));
	m_pXMLDoc->Release();
}
/*
*	函数名称:	Init()
*	说明:		初始化XML日志文件的工程信息
*	参数:	
*			无
*	返回:	无
*/
void CXMLLogfile::Init()
{
	IXMLDOMNode *pAppNameNode, *pTimestamp, *pDate, *pTime;;
	TCHAR        *szTemp = new TCHAR[MAX_PATH];
	HRESULT hr ;

	CTime	timeCur ;
	timeCur = CTime::GetCurrentTime();
	CString strDate, strTime;
	strDate = timeCur.Format(_T("%Y-%m-%d"));
	strTime = timeCur.Format(_T("%X"));

	//更改工程名称
	pAppNameNode = GetFirstLevelNode(_T("AppName"));
	hr = pAppNameNode->put_text(CComBSTR(AfxGetAppName()));
	pAppNameNode->Release();
//*	
	//时间戳
	ZeroMemory(szTemp,MAX_PATH);
	double timestamp = TimeStamp();
	_stprintf(szTemp,_T("%.3f"),timestamp);
	pTimestamp = GetFirstLevelNode(_T("Timestamp"));
	hr = pTimestamp->put_text(CComBSTR(szTemp));
	pTimestamp->Release();
//*/
	//日期
	pDate = GetFirstLevelNode(_T("Date"));
	hr = pDate->put_text(CComBSTR(strDate));
	pDate->Release();	

	//时间
	pTime = GetFirstLevelNode(_T("Time"));
	hr = pTime->put_text(CComBSTR(strTime));
	pTime->Release();

	delete szTemp;
	Flush();
}
/*
*	函数名称:	DumpComError(_com_error &e)
*	说明:		输出COM错误信息
*	参数:	
*			IN  _com_error &e	COM错误信息对象
*	返回:	无
*/
void CXMLLogfile::DumpComError(_com_error &e)
{
	_bstr_t bstrSource(e.Source());
	_bstr_t bstrDescription(e.Description());
	
	TRACE("Error\n");
	TRACE("\tCode = %08lx\n", e.Error());
	TRACE("\tCode meaning = %s\n", e.ErrorMessage());
	TRACE("\tSource = %s\n", (LPCSTR) bstrSource);
	TRACE("\tDescription = %s\n", (LPCSTR) bstrDescription);
}
/*
*	函数名称:	CreateLogFile(LPCTSTR lpszLogFilName)
*	说明:		创建原始的XML日志文件
*	参数:	
*			IN  LPCTSTR lpszLogFileName 文件名称
*	返回:	true 成功
*/
bool CXMLLogfile::CreateLogFile(LPCTSTR lpszLogFilName)
{
	IXMLDOMDocument *pXMLDoc = NULL;

	BSTR	bstr = NULL;
	VARIANT_BOOL	status;
	HRESULT hr;

	try
	{
		hr = CoCreateInstance(CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, 
			IID_IXMLDOMDocument, (void**)&pXMLDoc);

		if (FAILED(hr))
			_com_issue_error(hr);

		bstr = ::SysAllocString(wszLogOrig);
		ASSERT(NULL != bstr);
		hr = pXMLDoc->loadXML(bstr,&status);
		::SysFreeString(bstr);

		if (FAILED(hr))
			_com_issue_error(hr);

		if(status != VARIANT_TRUE)
		{
			return false;
		}

		hr = pXMLDoc->save(COleVariant(lpszLogFilName));
		if (FAILED(hr))
			_com_issue_error(hr);

		pXMLDoc->Release();
	}
	catch(_com_error &e)
	{
		DumpComError(e);
		return false;
	}
	return true;
}
/*
*	函数名称:	GetFirstLevelNode(LPCTSTR lpszNodeName)
*	说明:		根据名称查找第一层子节点指针,没有则判断是否创建
*	参数:	
*			IN  LPCTSTR lpszNodeName 节点名称
*			IN  BOOL	bCreate 是否创建
*	返回:	IXMLDOMNode *	节点指针
*/
IXMLDOMNode * CXMLLogfile::GetFirstLevelNode(LPCTSTR lpszNodeName,BOOL bCreate)
{
	IXMLDOMElement *pRootNode = NULL, *element = NULL;
	IXMLDOMNode    *pLogItem = NULL, *pResultNode = NULL;
	CComBSTR       szName;
	bool           bSecFound = false, bEntryFound = false;
//	wchar_t        *szTemp = new wchar_t[255];

	m_pXMLDoc->get_documentElement(&pRootNode);
	
	for(pRootNode->get_firstChild(&pLogItem); pLogItem != NULL; pLogItem->get_nextSibling(&pLogItem)) 
	{
		pLogItem->get_baseName(&szName);

		if(szName == CComBSTR(lpszNodeName)) 
		{
			pResultNode = pLogItem;
			break;
		}
	}

	if(pLogItem == NULL && bCreate) 
	{
		m_pXMLDoc->createElement(CComBSTR(lpszNodeName), &element);
		pRootNode->appendChild(element, &pLogItem);
		element->Release();
		pResultNode = pLogItem;
	}

	pRootNode->Release();
	
	return pResultNode;
}
/*
*	函数名称:	GetChildNode(LPCTSTR lpszParent, LPCTSTR lpszChild)
*	说明:		查找父节点下的某一子节点指针,没有则判断是否创建创建
*	参数:	
*			IN  LPCTSTR lpszParent 父节点名称
*			IN	LPCTSTR lpszChild	子节点名称
*			IN  BOOL	bCreate    是否创建
*	返回:	IXMLDOMNode *	子节点指针
*/
IXMLDOMNode * CXMLLogfile::GetChildNode(LPCTSTR lpszParent, LPCTSTR lpszChild,BOOL bCreate)
{
	IXMLDOMElement *pRootNode= NULL, *element= NULL;
	IXMLDOMNode    *pLogItem= NULL, *pLogData= NULL, *pResultNode= NULL;
	CComBSTR       szName;

	m_pXMLDoc->get_documentElement(&pRootNode);
	
	for(pRootNode->get_firstChild(&pLogItem); pLogItem != NULL; pLogItem->get_nextSibling(&pLogItem)) 
	{
		pLogItem->get_baseName(&szName);

		if(szName == CComBSTR(lpszParent)) 
		{
			for(pLogItem->get_firstChild(&pLogData); pLogData != NULL; pLogData->get_nextSibling(&pLogData)) 
			{
				pLogData->get_baseName(&szName);

				if(szName == CComBSTR(lpszChild)) 
				{
					pResultNode = pLogData;				
					break;
				}
			}

			if(pLogData == NULL && bCreate) 
			{
				m_pXMLDoc->createElement(CComBSTR(lpszChild), &element);
				pLogItem->appendChild(element, &pLogData);
				element->Release();
				pResultNode = pLogData;
			}
			pLogItem->Release();
			break;
		}
	}

	if(pLogItem == NULL && bCreate) 
	{
		m_pXMLDoc->createElement(CComBSTR(lpszParent), &element);
		pRootNode->appendChild(element, &pLogItem);
		element->Release();
		m_pXMLDoc->createElement(CComBSTR(lpszChild), &element);
		pLogItem->appendChild(element, &pLogData);
		element->Release();
		pResultNode = pLogData;
	}
	
	pRootNode->Release();

	return pResultNode;
}
/*
*	函数名称:	AppendNode(IXMLDOMNode * pXMLItem, LPCTSTR lpszNodeName, LPCTSTR lpszValue)
*	说明:		在XML中添加一节点,并赋值为 lpszValue
*	参数:	
*			IN  IXMLDOMNode *	pXMLItem 要添加节点的节点指针
*			IN	LPCTSTR lpszNodeName	添加的节点名称
*			IN  LPCTSTR lpszComment		值
*/
void CXMLLogfile::AppendNode(IXMLDOMNode * pXMLItem, LPCTSTR lpszNodeName, LPCTSTR lpszValue)
{
	IXMLDOMElement *element;
	IXMLDOMNode *pLogData;

	m_pXMLDoc->createElement(CComBSTR(lpszNodeName),&element);
	pXMLItem->appendChild(element,&pLogData);
	element->Release();

	pLogData->put_text(CComBSTR(lpszValue));
	pLogData->Release();	
}
/*
*	函数名称:	AppendItem(LPCTSTR lpszFileName,LPCTSTR lpszComment)
*	说明:		在XML中添加一条日志
*	参数:	
*			IN	LPCTSTR lpszFileName	文件信息
*			IN  LPCTSTR lpszComment		错误信息
*/
void CXMLLogfile::AppendItem(LPCTSTR lpszFileName,LPCTSTR lpszComment)
{
	IXMLDOMElement *pRootNode, *element;
	IXMLDOMNode    *nLogItem;
	CComBSTR       szName;
	HRESULT hr;

	CTime timeCur ;
	timeCur = CTime::GetCurrentTime();
	CString strDate, strTime;
	strDate = timeCur.Format(_T("%Y-%m-%d"));
	strTime = timeCur.Format(_T("%X"));
	
	hr = m_pXMLDoc->get_documentElement(&pRootNode);

	m_pXMLDoc->createElement(CComBSTR(_T("LogItem")),&element);
	pRootNode->appendChild(element,&nLogItem);
	element->Release();

	AppendNode(nLogItem,_T("Date"),strDate);

	AppendNode(nLogItem,_T("Time"),strTime);

	AppendNode(nLogItem,_T("Filename"),lpszFileName);

	AppendNode(nLogItem,_T("comment"),lpszComment);


	pRootNode->Release();
}
/*
*	函数名称:	Flush()
*	说明:		将缓冲区内数据写到磁盘保存XML文件
*	参数:	
*				无
*/
void CXMLLogfile::Flush()
{
	m_pXMLDoc->save(COleVariant(m_strFileName));
}
/*
*	函数名称:	Log(LPCTSTR lpszFilName,LPCTSTR s,...)
*	说明:		添加一条日值记录
*	参数:	
*				LPCTSTR lpszFileName	文件信息
*				LPCTSTR	s				其他错误信息
*	EXAMPLE:
*			Log(__FILE__,"%ld line error!!",__LINE__)
*/
void CXMLLogfile::Log(LPCTSTR lpszFilName,LPCTSTR s,...)
{
	static TCHAR szBuff[1024];
	va_list argptr;
	int cnt;

	va_start(argptr, s);
	cnt = _vstprintf(szBuff, s, argptr);
	va_end(argptr);
	
	AppendItem(lpszFilName,szBuff);
	Flush();
}
/*
*	函数名称:	ClearAll()
*	说明:		清除日值
*	参数:	
*				无
*	返回值:		 成功 true
*/
bool CXMLLogfile::ClearAll()
{
	IXMLDOMElement *pRootNode= NULL;
	IXMLDOMNode    *pLogItem= NULL, *pLogData= NULL, *pOldNode= NULL, *pNextNode ,*pPreviousNode;
	CComBSTR       szName;
	HRESULT		hr ;
	m_pXMLDoc->get_documentElement(&pRootNode);
	try
	{
		pRootNode->get_lastChild(&pLogItem);
		do
		{
			pLogItem->get_previousSibling(&pPreviousNode);
				
			pLogItem->get_baseName(&szName);
			if(szName == CComBSTR(_T("LogItem"))) 
			{
				pLogItem->get_firstChild(&pLogData);
				do
				{
					pLogData->get_nextSibling(&pNextNode);

					pLogData->get_baseName(&szName);
					hr = pLogItem->removeChild(pLogData,&pOldNode);
					if (FAILED(hr))
						_com_issue_error(hr);
					pOldNode->Release();
					pOldNode = NULL;

					pLogData = pNextNode;
				}while(pLogData != NULL);

				hr = pRootNode->removeChild(pLogItem,&pOldNode);

				if (FAILED(hr))
				_com_issue_error(hr);
			}
			
			pLogItem = pPreviousNode;
		}while(pLogItem != NULL);
		pRootNode->Release();
	}
	catch(_com_error &e)
	{
		pRootNode->Release();
		DumpComError(e);
		return false;
	}
	Flush();
	return true;
}

(全文完)
关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 myfaq.com.cn All rights reserved. www.myfaq.com.cn 版权所有