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

📄 xml.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// XML.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include "StdAfx.h"
#include "Shareaza.h"
#include "XML.h"

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


//////////////////////////////////////////////////////////////////////
// CXMLNode construction

CXMLNode::CXMLNode(CXMLElement* pParent, LPCTSTR pszName)
{
	m_nNode		= xmlNode;
	m_pParent	= pParent;
	if ( pszName ) m_sName = pszName;
}

CXMLNode::~CXMLNode()
{
}

//////////////////////////////////////////////////////////////////////
// CXMLNode parsing

BOOL CXMLNode::ParseMatch(LPCTSTR& pszBase, LPCTSTR pszToken)
{
	LPCTSTR pszXML = pszBase;
	int nParse = 0;

	for ( ; *pszXML == ' ' || *pszXML == '\t' || *pszXML == '\r' || *pszXML == '\n' ; pszXML++, nParse++ );
	if ( ! *pszXML ) return FALSE;

	for ( ; *pszXML && *pszToken ; pszXML++, pszToken++, nParse++ )
	{
		if ( *pszXML != *pszToken ) return FALSE;
	}

	pszBase += nParse;

	return TRUE;
}

BOOL CXMLNode::ParseIdentifier(LPCTSTR& pszBase, CString& strIdentifier)
{
	LPCTSTR pszXML = pszBase;
	int nParse = 0;

	for ( ; *pszXML == ' ' || *pszXML == '\t' || *pszXML == '\r' || *pszXML == '\n' ; pszXML++, nParse++ );
	if ( ! *pszXML ) return FALSE;

	int nIdentifier = 0;
	for ( ; *pszXML && ( _istalnum( *pszXML ) || *pszXML == ':' || *pszXML == '_' ) ; pszXML++, nIdentifier++ );
	if ( ! nIdentifier ) return FALSE;

	pszBase += nParse;
	_tcsncpy( strIdentifier.GetBuffer( nIdentifier ), pszBase, nIdentifier );
	strIdentifier.ReleaseBuffer( nIdentifier );
	pszBase += nIdentifier;

	return TRUE;
}

//////////////////////////////////////////////////////////////////////
// CXMLNode string to value

CString CXMLNode::StringToValue(LPCTSTR& pszXML, int nLength)
{
	CString strValue;

	if ( ! nLength || ! *pszXML ) return strValue;

	LPTSTR pszValue = strValue.GetBuffer( nLength + 4 );
	LPTSTR pszOut = pszValue;
	
	LPTSTR pszNull = (LPTSTR)pszXML + nLength;
	TCHAR cNull = *pszNull;
	*pszNull = 0;

	while ( *pszXML && pszXML < pszNull )
	{
		if ( _istspace( *pszXML ) )
		{
			if ( pszValue != pszOut ) *pszOut++ = ' ';
			pszXML++;
			while ( *pszXML && _istspace( *pszXML ) ) pszXML++;
			if ( ! *pszXML || pszXML >= pszNull ) break;
		}

		if ( *pszXML == '&' )
		{
			pszXML++;
			if ( ! *pszXML || pszXML >= pszNull ) break;

			if ( _tcsnicmp( pszXML, _T("amp;"), 4 ) == 0 )
			{
				*pszOut++ = '&';
				pszXML += 4;
			}
			else if ( _tcsnicmp( pszXML, _T("lt;"), 3 ) == 0 )
			{
				*pszOut++ = '<';
				pszXML += 3;
			}
			else if ( _tcsnicmp( pszXML, _T("gt;"), 3 ) == 0 )
			{
				*pszOut++ = '>';
				pszXML += 3;
			}
			else if ( _tcsnicmp( pszXML, _T("quot;"), 5 ) == 0 )
			{
				*pszOut++ = '\"';
				pszXML += 5;
			}
			else if ( _tcsnicmp( pszXML, _T("apos;"), 5 ) == 0 )
			{
				*pszOut++ = '\'';
				pszXML += 5;
			}
			else if ( _tcsnicmp( pszXML, _T("nbsp;"), 5 ) == 0 )
			{
				*pszOut++ = ' ';
				pszXML += 5;
			}
			else if ( *pszXML == '#' )
			{
				int nChar;
				pszXML++;
				if ( ! *pszXML || pszXML >= pszNull || ! _istdigit( *pszXML ) ) break;

				if ( _stscanf( pszXML, _T("%lu;"), &nChar ) == 1 )
				{
					*pszOut++ = (TCHAR)nChar;
					while ( *pszXML && *pszXML != ';' ) pszXML++;
					if ( ! *pszXML || pszXML >= pszNull ) break;
					pszXML++;
				}
			}
			else
			{
				*pszOut++ = '&';
			}
		}
		else
		{
			*pszOut++ = *pszXML++;
		}
	}
	
	ASSERT( pszNull == pszXML );
	*pszNull = cNull;
	
	ASSERT( pszOut - pszValue <= nLength );
	strValue.ReleaseBuffer( (int)( pszOut - pszValue ) );

	return strValue;
}

//////////////////////////////////////////////////////////////////////
// CXMLNode value to string

#define V2S_APPEND(x,y)	\
	if ( (x) > nOut ) \
	{ \
		strXML.ReleaseBuffer( nLen + nOut ); \
		nOut += (x) + 16; \
		pszOut = strXML.GetBuffer( nLen + nOut ) + nLen; \
	} \
	{ for ( LPCTSTR pszIn = (y) ; *pszIn ; nOut--, nLen++ ) *pszOut++ = *pszIn++; }

void CXMLNode::ValueToString(LPCTSTR pszValue, CString& strXML)
{
	int nLen = strXML.GetLength();
	int nOut = (int)_tcslen( pszValue );
	LPTSTR pszOut = strXML.GetBuffer( nLen + nOut ) + nLen;
	
	for ( ; *pszValue ; pszValue++ )
	{
#ifdef UNICODE
		int nChar = (int)(unsigned short)*pszValue;
#else
		int nChar = (int)(unsigned char)*pszValue;
#endif
		
		switch ( nChar )
		{
		case '&':
			V2S_APPEND( 5, _T("&amp;") );
			break;
		case '<':
			V2S_APPEND( 4, _T("&lt;") );
			break;
		case '>':
			V2S_APPEND( 4, _T("&gt;") );
			break;
		case '\"':
			V2S_APPEND( 6, _T("&quot;") );
			break;
		case '\'':
			V2S_APPEND( 6, _T("&apos;") );
			break;
		default:
			if ( nChar > 127 )
			{
				CString strItem;
				strItem.Format( _T("&#%lu;"), nChar );
				V2S_APPEND( strItem.GetLength(), strItem );
			}
			else if ( nOut > 0 )
			{
				*pszOut++ = nChar;
				nOut--;
				nLen++;
			}
			else
			{
				strXML.ReleaseBuffer( nLen + nOut );
				nOut += 16;
				pszOut = strXML.GetBuffer( nLen + nOut ) + nLen;
				*pszOut++ = nChar;
				nOut--;
				nLen++;
			}
			break;
		}
	}
	
	strXML.ReleaseBuffer( nLen );
}

//////////////////////////////////////////////////////////////////////
// CXMLNode serialize

#ifdef _AFX

void CXMLNode::Serialize(CArchive& ar)
{
	if ( ar.IsStoring() )
	{
		ar << m_sName;
		ar << m_sValue;
	}
	else
	{
		ar >> m_sName;
		ar >> m_sValue;
	}
}

#endif

//////////////////////////////////////////////////////////////////////
// CXMLNode string helper

void CXMLNode::UniformString(CString& str)
{
	static LPCTSTR pszOK = _T("'-&");

	str.TrimLeft();
	str.TrimRight();
	
	BOOL bSpace = TRUE;
	
	for ( int nPos = 0 ; nPos < str.GetLength() ; nPos++ )
	{
#ifdef UNICODE
		int nChar = (int)(unsigned short)str.GetAt( nPos );
#else
		int nChar = (int)(unsigned char)str.GetAt( nPos );
#endif
		
		if ( nChar <= 32 )
		{
			if ( bSpace )
			{
				str = str.Left( nPos ) + str.Mid( nPos + 1 );
				nPos--;
			}
			else
			{
				if ( nChar != 32 ) str.SetAt( nPos, 32 );
				bSpace = TRUE;
			}
		}
		else if ( ! _istalnum( nChar ) && nChar < 0xC0 && _tcschr( pszOK, nChar ) == NULL )
		{
			str = str.Left( nPos ) + str.Mid( nPos + 1 );
			nPos--;
		}
		else
		{
			bSpace = FALSE;
		}
	}
}


//////////////////////////////////////////////////////////////////////
// CXMLElement construction

CXMLElement::CXMLElement(CXMLElement* pParent, LPCTSTR pszName) : CXMLNode( pParent, pszName )
{
	m_nNode = xmlElement;
}

CXMLElement::~CXMLElement()
{
	DeleteAllElements();
	DeleteAllAttributes();
}

//////////////////////////////////////////////////////////////////////
// CXMLElement clone

CXMLElement* CXMLElement::Clone(CXMLElement* pParent)
{
	CXMLElement* pClone = new CXMLElement( pParent, m_sName );
	
	for ( POSITION pos = GetAttributeIterator() ; pos ; )
	{
		CXMLAttribute* pAttribute = GetNextAttribute( pos )->Clone( pClone );
		CString strName( pAttribute->m_sName );

		strName.MakeLower();
		pClone->m_pAttributes.SetAt( strName, pAttribute );
	}

	for ( pos = GetElementIterator() ; pos ; )
	{
		CXMLElement* pElement = GetNextElement( pos );
		pClone->m_pElements.AddTail( pElement->Clone( pClone ) );
	}

	pClone->m_sValue = m_sValue;

	return pClone;
}

//////////////////////////////////////////////////////////////////////
// CXMLElement delete

void CXMLElement::DeleteAllElements()
{
	for ( POSITION pos = m_pElements.GetHeadPosition() ; pos ; )
	{
		delete (CXMLElement*)m_pElements.GetNext( pos );
	}
	m_pElements.RemoveAll();
}

void CXMLElement::DeleteAllAttributes()
{
	for ( POSITION pos = m_pAttributes.GetStartPosition() ; pos ; )
	{
		CXMLAttribute* pAttribute = NULL;
		CString strName;

		m_pAttributes.GetNextAssoc( pos, strName, XMLVOID(pAttribute) );
		delete pAttribute;
	}
	m_pAttributes.RemoveAll();
}

//////////////////////////////////////////////////////////////////////
// CXMLElement to string

CString CXMLElement::ToString(BOOL bHeader, BOOL bNewline)
{
	CString strXML;
	if ( bHeader ) strXML = _T("<?xml version=\"1.0\"?>");
	if ( bNewline ) strXML += _T("\r\n");
	ToString( strXML, bNewline );
	ASSERT( strXML.GetLength() == _tcslen(strXML) );
	return strXML;
}

void CXMLElement::ToString(CString& strXML, BOOL bNewline)
{
	strXML += '<' + m_sName;
	
	for ( POSITION pos = GetAttributeIterator() ; pos ; )
	{
		strXML += ' ';
		CXMLAttribute* pAttribute = GetNextAttribute( pos );
		pAttribute->ToString( strXML );
	}
	
	pos = GetElementIterator();
	
	if ( pos == NULL && m_sValue.IsEmpty() )
	{
		strXML += _T("/>");
		if ( bNewline ) strXML += _T("\r\n");
		return;
	}
	
	strXML += '>';
	if ( bNewline && pos ) strXML += _T("\r\n");
	
	while ( pos )
	{
		CXMLElement* pElement = GetNextElement( pos );
		pElement->ToString( strXML, bNewline );
	}
	
	ValueToString( m_sValue, strXML );
	
	strXML += _T("</") + m_sName + '>';
	if ( bNewline ) strXML += _T("\r\n");
}

//////////////////////////////////////////////////////////////////////
// CXMLElement from string

CXMLElement* CXMLElement::FromString(LPCTSTR pszXML, BOOL bHeader)
{
	CXMLElement* pElement	= NULL;
	LPCTSTR pszElement		= NULL;
	
#ifdef _AFX
	try

⌨️ 快捷键说明

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