⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlparse.cpp

📁 一个完整强大的xml文件解析的程序
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//nieo
//x_TextToDoc
/*
	//alter by nieo 2003, for chinese support
	CString strReturn(szText);
	strReturn.Replace(_T("&"),_T("&"));
	strReturn.Replace(_T("<"),_T("&lt;"));
	strReturn.Replace(_T(">"),_T("&gt;"));
	if(bAttrib)
	{
		strReturn.Replace(_T("\'"),_T("&apos;"));
		strReturn.Replace(_T("\""),_T("&quot;"));
	}
	return strReturn;

	//alter by nieo 2003,for chinese support
	CString strReturn(m_csDoc.Mid(nLeft,nRight-nLeft+1));
	strReturn.Replace(_T("&amp;"),_T("&"));
	strReturn.Replace(_T("&lt;"),_T("<"));
	strReturn.Replace(_T("&gt;"),_T(">"));
	strReturn.Replace(_T("&apos;"),_T("\'"));
	strReturn.Replace(_T("&quot;"),_T("\""));
	return strReturn;
	*/
//
// XMLParse	 Release 6.1 Lite
// Copyright (C) 1999-2001 First Objective Software, Inc. All rights reserved
// This entire notice must be retained in this source code
// Redistributing this source code requires written permission
// This software is provided "as is", with no warranty.
// Latest fixes enhancements and documentation at www.firstobject.com

//patch history
//	nieo add x_SetData 2003-08-27


#include "stdafx.h"
#include "oc_xml.h"

#ifdef _MBCS
#pragma message( "Note: MBCS build (not UTF-8)" )
// For UTF-8, remove _MBCS from project settings C/C++ preprocessor definitions
#endif

// Defines for Windows CE
#ifdef _WIN32_WCE
#define _tclen(p) 1
#define _tccpy(p1,p2) *(p1)=*(p2)
#endif

// Customization
#define x_EOL _T("\r\n") // can be \r\n or \n or empty
#define x_EOLLEN (sizeof(x_EOL)/sizeof(_TCHAR)-1) // string length of x_EOL
#define x_ATTRIBQUOTE _T("\"") // can be double or single quote

using namespace std;

 string CXMLParse::_FormatStringFromBin(char * pData,int nLen)
{
	CString strReturn;
	for(int i=0;i<nLen;i++)
	{
		char b = pData[i];
		CString s;
		s.Format("%02x",b);
		strReturn+= s;
	}
	return string(strReturn);
}

void CXMLParse::_FormatBinFromString(const char * strSource,char** ppData,int* pLen)
{
	*ppData=NULL;
	*pLen = 0;
	int nLen = (int)strlen(strSource);
	if(nLen<=0)
		return;
	char* pSrc = (char*)strSource;
	char* pTmp = pSrc;
	*pLen = nLen/2;
	if(nLen%2)*pLen ++;
	*ppData = new char[*pLen];
	int nIndex = 0;
	while(pTmp-pSrc<nLen)
	{
		char h = *pTmp;
		char l = *(pTmp+1);
		int nH = atoi(&h);
		int nL = atoi(&l);
		BYTE b = nH*0x10+nL;
		pTmp+=2;
		(*ppData)[nIndex++] = b;
	}
}

void CXMLParse::GetData(char** ppData,int* pLen)
{
	string str = GetData();
	_FormatBinFromString(str.c_str(),ppData,pLen);
}

void CXMLParse::GetDoc(char** ppBuf,int* pnLen)
{ 
	*pnLen = this->m_strDoc.GetLength();
	*ppBuf = NULL;
	if(*pnLen>0)
	{
		*ppBuf = new char[*pnLen];
		memcpy(*ppBuf,this->m_strDoc,*pnLen);
	}
}
void CXMLParse::operator=( const CXMLParse& markup )
{
	m_iPosParent = markup.m_iPosParent;
	m_iPos = markup.m_iPos;
	m_iPosChild = markup.m_iPosChild;
	m_iPosFree = markup.m_iPosFree;
	m_iPosDeleted = markup.m_iPosDeleted;
	m_nNodeType = markup.m_nNodeType;
	m_nNodeOffset = markup.m_nNodeOffset;
	m_nNodeLength = markup.m_nNodeLength;
	m_strDoc = markup.m_strDoc;
	m_strError = markup.m_strError;
	m_nFlags = markup.m_nFlags;

	// Copy used part of the index array
	m_aPos.RemoveAll();
	m_aPos.nSize = m_iPosFree;
	if ( m_aPos.nSize < 8 )
		m_aPos.nSize = 8;
	m_aPos.nSegs = m_aPos.SegsUsed();
	if ( m_aPos.nSegs )
	{
		m_aPos.pSegs = (ElemPos**)(new char[m_aPos.nSegs*sizeof(char*)]);
		int nSegSize = 1 << m_aPos.PA_SEGBITS;
		for ( int nSeg=0; nSeg < m_aPos.nSegs; ++nSeg )
		{
			if ( nSeg + 1 == m_aPos.nSegs )
				nSegSize = m_aPos.GetSize() - (nSeg << m_aPos.PA_SEGBITS);
			m_aPos.pSegs[nSeg] = (ElemPos*)(new char[nSegSize*sizeof(ElemPos)]);
			memcpy( m_aPos.pSegs[nSeg], markup.m_aPos.pSegs[nSeg], nSegSize*sizeof(ElemPos) );
		}
	}

	// Copy SavedPos map
	m_mapSavedPos.RemoveAll();
	if ( markup.m_mapSavedPos.pTable )
	{
		m_mapSavedPos.AllocMapTable();
		for ( int nSlot=0; nSlot < SavedPosMap::SPM_SIZE; ++nSlot )
		{
			SavedPos* pCopySavedPos = markup.m_mapSavedPos.pTable[nSlot];
			if ( pCopySavedPos )
			{
				int nCount = 0;
				while ( pCopySavedPos[nCount].nSavedPosFlags & SavedPosMap::SPM_USED )
				{
					++nCount;
					if ( pCopySavedPos[nCount-1].nSavedPosFlags & SavedPosMap::SPM_LAST )
						break;
				}
				SavedPos* pNewSavedPos = new SavedPos[nCount];
				for ( int nCopy=0; nCopy<nCount; ++nCopy )
					pNewSavedPos[nCopy] = pCopySavedPos[nCopy];
				pNewSavedPos[nCount-1].nSavedPosFlags |= SavedPosMap::SPM_LAST;
				m_mapSavedPos.pTable[nSlot] = pNewSavedPos;
			}
		}
	}

}

bool CXMLParse::SetDoc(char* pBuf,int len)
{
	this->m_strDoc.Empty();
	memcpy(this->m_strDoc.GetBufferSetLength(len),pBuf,len);
	//_remote_header();
	return x_ParseDoc();
}

void CXMLParse::_remote_header()
{
	CString header = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>";
	this->m_strDoc.Replace(header,"");
}

bool CXMLParse::SetDoc( const char * szDoc )
{
	// Set document text
	if ( szDoc )
		m_strDoc = szDoc;
	else
		m_strDoc.Empty();

	m_strError.Empty();
	//_remote_header();
	return x_ParseDoc();
};

bool CXMLParse::IsWellFormed()
{
	if ( m_aPos.GetSize()
			&& ! (m_aPos[0].nFlags & MNF_ILLFORMED)
			&& m_aPos[0].iElemChild
			&& ! m_aPos[m_aPos[0].iElemChild].iElemNext )
		return true;
	return false;
}

bool CXMLParse::Load( const char * szFileName )
{
	if ( ! ReadTextFile(szFileName, m_strDoc, &m_strError, &m_nFlags) )
		return false;
	return x_ParseDoc();
}

bool CXMLParse::ReadTextFile( const char * szFileName, CString& strDoc, CString* pstrError, int* pnFlags )
{
	// Static utility method to load text file into strDoc
	//
	// Open file to read binary
	FILE* fp = _tfopen( szFileName, _T("rb") );
	if ( ! fp )
	{
		if ( pstrError )
			*pstrError = strerror(errno);
		return false;
	}

	// Set flags to 0 unless flags argument provided
	int nFlags = pnFlags?*pnFlags:0;
	_TCHAR szDescBOM[20] = {0};
	strDoc.Empty();

	// Get file length
	fseek( fp, 0, SEEK_END );
	int nFileByteLen = ftell( fp );
	fseek( fp, 0, SEEK_SET );


#if defined(_UNICODE) // convert file to wide char
	int nWideLen = 0;
	if ( nFileByteLen )
	{
		char* pBuffer = new char[nFileByteLen];
		fread( pBuffer, nFileByteLen, 1, fp );
		// For ANSI files, replace CP_UTF8 with CP_ACP in both places
		nWideLen = MultiByteToWideChar(CP_UTF8,0,pBuffer,nFileByteLen,NULL,0);
		MultiByteToWideChar(CP_UTF8,0,pBuffer,nFileByteLen,strDoc.GetBuffer(nWideLen),nWideLen);
		strDoc.ReleaseBuffer( nWideLen );
		delete [] pBuffer;
	}
	if ( pstrError )
		(*pstrError).Format(_T("%s%d bytes to %d wide chars"),szDescBOM,nFileByteLen,nWideLen);
#else // read file directly
	if ( nFileByteLen )
	{
		fread( strDoc.GetBuffer(nFileByteLen), nFileByteLen, 1, fp );
		strDoc.ReleaseBuffer( nFileByteLen );
	}
	if ( pstrError )
		(*pstrError).Format( _T("%s%d bytes"), szDescBOM, nFileByteLen );
#endif
	fclose( fp );
	if ( pnFlags )
		*pnFlags = nFlags;
	return true;
}

bool CXMLParse::Save( const char * szFileName )
{
	return WriteTextFile( szFileName, m_strDoc, &m_strError, &m_nFlags );
}

bool CXMLParse::WriteTextFile( const char * szFileName, CString& strDoc, CString* pstrError, int* pnFlags )
{
	// Static utility method to save strDoc to text file
	//
	// Open file to write binary
	bool bSuccess = true;
	FILE* fp = _tfopen( szFileName, _T("wb") );
	if ( ! fp )
	{
		if ( pstrError )
			*pstrError = strerror(errno);
		return false;
	}

	// Set flags to 0 unless flags argument provided
	int nFlags = pnFlags?*pnFlags:0;
	_TCHAR szDescBOM[20] = {0};

	// Get document length
	int nDocLength = strDoc.GetLength();


#if defined( _UNICODE )
	int nMBLen = 0;
	if ( nDocLength )
	{
		// For ANSI files, replace CP_UTF8 with CP_ACP in both places
		nMBLen = WideCharToMultiByte(CP_UTF8,0,strDoc,nDocLength,NULL,0,NULL,NULL);
		char* pBuffer = new char[nMBLen+1];
		WideCharToMultiByte(CP_UTF8,0,strDoc,nDocLength,pBuffer,nMBLen+1,NULL,NULL);
		bSuccess = ( fwrite( pBuffer, nMBLen, 1, fp ) == 1 );
		delete [] pBuffer;
	}
	if ( pstrError )
		(*pstrError).Format( _T("%d wide chars to %s%d bytes"), nDocLength, szDescBOM, nMBLen );
#else // MBCS or UTF-8
	if ( nDocLength )
	{
		CString strDocWrite = strDoc; // reference unless converted
		nDocLength = strDocWrite.GetLength();
		bSuccess = ( fwrite( (LPCTSTR)strDocWrite, nDocLength, 1, fp ) == 1 );
	}
	if ( pstrError )
		(*pstrError).Format( _T("%s%d bytes"), szDescBOM, nDocLength );
#endif
	
	if ( ! bSuccess && pstrError )
		*pstrError = strerror(errno);
	fclose(fp);
	if ( pnFlags )
		*pnFlags = nFlags;
	return bSuccess;
}

bool CXMLParse::FindElem( const char * szName )
{
	// Change current position only if found
	//
	if ( m_aPos.GetSize() )
	{
		int iPos = x_FindElem( m_iPosParent, m_iPos, szName );
		if ( iPos )
		{
			// Assign new position
			x_SetPos( m_aPos[iPos].iElemParent, iPos, 0 );
			return true;
		}
	}
	return false;
}

bool CXMLParse::FindChildElem( const char * szName )
{
	// Change current child position only if found
	//
	// Shorthand: call this with no current main position
	// means find child under root element
	if ( ! m_iPos )
		FindElem();

	int iPosChild = x_FindElem( m_iPos, m_iPosChild, szName );
	if ( iPosChild )
	{
		// Assign new position
		int iPos = m_aPos[iPosChild].iElemParent;
		x_SetPos( m_aPos[iPos].iElemParent, iPos, iPosChild );
		return true;
	}

	return false;
}

string CXMLParse::EscapeText( const char * szText, int nFlags )
{
	// Convert text as seen outside XML document to XML friendly
	// replacing special characters with ampersand escape codes
	// E.g. convert "6>7" to "6&gt;7"
	//
	// &lt;   less than
	// &amp;  ampersand
	// &gt;   greater than
	//
	// and for attributes:
	//
	// &apos; apostrophe or single quote
	// &quot; double quote
	//

	if(szText==NULL)
		return "";

	static LPCTSTR szaReplace[] = { _T("&lt;"),_T("&amp;"),_T("&gt;"),_T("&apos;"),_T("&quot;") };
	LPCTSTR pFind = (nFlags&MNF_ESCAPEQUOTES)?_T("<&>\'\""):_T("<&>");
	CString strText;
	LPCTSTR pSource = szText;
	int nDestSize = (int)_tcslen(pSource);
	nDestSize += nDestSize / 10 + 7;
	_TCHAR* pDest = strText.GetBuffer(nDestSize);
	int nLen = 0;
	_TCHAR cSource = *pSource;
	LPCTSTR pFound;
	while ( cSource )
	{
		if ( nLen > nDestSize - 6 )
		{
			strText.ReleaseBuffer(nLen);
			nDestSize *= 2;
			pDest = strText.GetBuffer(nDestSize);
		}
		if ( (pFound=_tcschr(pFind,cSource)) != NULL )
		{
			bool bIgnoreAmpersand = false;
			if ( (nFlags&MNF_WITHREFS) && *pFound == _T('&') )
			{
				// Do not replace ampersand if it is start of any entity reference
				// &[#_:A-Za-zU][_:-.A-Za-z0-9U]*; where U is > 0x7f
				LPCTSTR pCheckEntity = pSource;
				++pCheckEntity;
				_TCHAR c = *pCheckEntity;
				if ( (c>=_T('A')&&c<=_T('Z')) || (c>=_T('a')&&c<=_T('z'))
						|| c==_T('#') || c==_T('_') || c==_T(':') || c>0x7f )
				{
					while ( 1 )
					{
						pCheckEntity += _tclen( pCheckEntity );
						c = *pCheckEntity;
						if ( c == _T(';') )
						{
							int nEntityLen = (int)(pCheckEntity - pSource) + 1;
							_tcsncpy(&pDest[nLen],pSource,nEntityLen);
							nLen += nEntityLen;
							pSource = pCheckEntity;
							bIgnoreAmpersand = true;
						}
						else if ( (c>=_T('A')&&c<=_T('Z')) || (c>=_T('a')&&c<=_T('z')) || (c>=_T('0')&&c<=_T('9'))
								|| c==_T('_') || c==_T(':') || c==_T('-') || c==_T('.') || c>0x7f )
							continue;
						break;
					}
				}
			}
			if ( ! bIgnoreAmpersand )
			{
				pFound = szaReplace[pFound-pFind];
				_tcscpy(&pDest[nLen],pFound);
				nLen += (int)_tcslen(pFound);
			}
		}
		else
		{
			_tccpy( &pDest[nLen], pSource );
			nLen += (int)_tclen( pSource );
		}
		pSource += _tclen( pSource );
		cSource = *pSource;
	}
	strText.ReleaseBuffer(nLen);
	return string(strText);
}

string CXMLParse::UnescapeText( const char * szText, int nTextLength /*=-1*/ )
{
	// Convert XML friendly text to text as seen outside XML document
	// ampersand escape codes replaced with special characters e.g. convert "6&gt;7" to "6>7"
	// ampersand numeric codes replaced with character e.g. convert &#60; to <
	// Conveniently the result is always the same or shorter in byte length
	//
	static LPCTSTR szaCode[] = { _T("lt;"),_T("amp;"),_T("gt;"),_T("apos;"),_T("quot;") };
	static int anCodeLen[] = { 3,4,3,5,5 };
	static LPCTSTR szSymbol = _T("<&>\'\"");
	CString strText;
	LPCTSTR pSource = szText;
	if ( nTextLength == -1 )
		nTextLength = (int)_tcslen(szText);
	_TCHAR* pDest = strText.GetBuffer( nTextLength );
	int nLen = 0;
	int nCharLen;
	int nChar = 0;
	while ( nChar < nTextLength )
	{
		if ( pSource[nChar] == _T('&') )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -