xmlfile.cpp

来自「管理项目进度工具的原代码」· C++ 代码 · 共 1,413 行 · 第 1/3 页

CPP
1,413
字号
	// else
	return ValueMatches(pXITest->GetValue(), bIgnoreCase);
}

BOOL CXmlItem::ValueMatches(LPCTSTR szValue, BOOL bIgnoreCase) const
{
	if (bIgnoreCase)
		return (m_sValue.CompareNoCase(szValue) == 0);
	
	// else
	return (m_sValue == szValue);
}

BOOL CXmlItem::ItemValueMatches(const CXmlItem* pXITest, LPCTSTR szItemName, BOOL bIgnoreCase) const
{
	if (!szItemName || !*szItemName)
		return FALSE;
	
	const CXmlItem* pXIItem = GetItem(szItemName);
	const CXmlItem* pXITestItem = pXITest->GetItem(szItemName);
	
	if (pXIItem && pXITestItem)
		return pXIItem->ValueMatches(pXITestItem, bIgnoreCase);
	
	// else
	return FALSE;
}

void CXmlItem::SortItems(LPCTSTR szItemName, LPCTSTR szKeyName, BOOL bAscending)
{
	SortItems(szItemName, szKeyName, XISK_STRING, bAscending);
}

void CXmlItem::SortItemsI(LPCTSTR szItemName, LPCTSTR szKeyName, BOOL bAscending)
{
	SortItems(szItemName, szKeyName, XISK_INT, bAscending);
}

void CXmlItem::SortItemsF(LPCTSTR szItemName, LPCTSTR szKeyName, BOOL bAscending)
{
	SortItems(szItemName, szKeyName, XISK_FLOAT, bAscending);
}

void CXmlItem::SortItems(LPCTSTR szItemName, LPCTSTR szKeyName, XI_SORTKEY nKey, BOOL bAscending)
{
	if (!szItemName || !szKeyName)
		return;
	
	// 1. sort immediate children first
	CXmlItem* pXIItem = GetItem(szItemName);
	
	if (!pXIItem)
		return;
	
	// make sure item has key value
	if (!pXIItem->GetItem(szKeyName))
		return;
	
	// make sure at least one sibling exists
	BOOL bContinue = (pXIItem->GetSibling() != NULL);
	
	while (bContinue)
	{
		CXmlItem* pXIPrev = NULL;
		CXmlItem* pXISibling = NULL;
		
		// get this again because we have to anyway 
		// for subsequent loops
		pXIItem = GetItem(szItemName);
		
		// reset continue flag so that if there are no
		// switches then the sorting is done
		bContinue = FALSE;
		pXISibling = pXIItem->GetSibling();
		
		while (pXISibling)
		{
			int nCompare = CompareItems(pXIItem, pXISibling, szKeyName, nKey);
			
			if (!bAscending)
				nCompare = -nCompare;
			
			if (nCompare > 0)
			{
				// switch items
				if (pXIPrev)
					pXIPrev->m_pSibling = pXISibling;
				
				else // we're at the head of the chain
					m_mapItems[szItemName] = pXISibling;
				
				pXIItem->m_pSibling = pXISibling->m_pSibling;
				pXISibling->m_pSibling = pXIItem;
				pXIPrev = pXISibling;
				
				bContinue = TRUE; // loop once more
			}
			else
			{
				pXIPrev = pXIItem;
				pXIItem = pXISibling;
			}

			pXISibling = pXIItem->GetSibling(); // next
		}
	}
	
	// 2. sort children's children
	pXIItem = GetItem(szItemName);
	
	while (pXIItem)
	{
		pXIItem->SortItems(szItemName, szKeyName, nKey, bAscending);
		pXIItem = pXIItem->GetSibling();
	}
}

int CXmlItem::CompareItems(const CXmlItem* pXIItem1, const CXmlItem* pXIItem2, 
						   LPCTSTR szKeyName, XI_SORTKEY nKey)
{
	LPCTSTR szValue1 = pXIItem1->GetItemValue(szKeyName);
	LPCTSTR szValue2 = pXIItem2->GetItemValue(szKeyName);
	
	double dDiff = 0;
	
	switch (nKey)
	{
	case XISK_STRING:
		dDiff = (double)CString(szValue1).CompareNoCase(szValue2);
		break;
		
	case XISK_INT:
		dDiff = (double)(atoi(szValue1) - atoi(szValue2));
		break;
		
	case XISK_FLOAT:
		dDiff = atof(szValue1) - atof(szValue2);
		break;
	}
	
	return (dDiff < 0) ? -1 : ((dDiff > 0) ? 1 : 0);
}

BOOL CXmlItem::IsCDATA() const 
{ 
	return m_bCData;// || (m_sName == CDATA); 
}

void CXmlItem::ValidateString(CString& sText, char cReplace)
{
	// remove nasties that XML does not like
	int nLen = sText.GetLength();

	for(int nChar = 0; nChar < nLen; nChar++)
	{
		UINT c = sText[nChar];

		// some specific chars we don't like
		switch (c)
		{
		case 0x2026: // ellipsis
			sText.SetAt(nChar, cReplace);
			break;
		}
		
		if ((c < 0x20 && (c == 0x09 || c == 0x0A || c == 0x0D)) || 
			(c >= 0x20 && c < 0x82) || c > 0x9F) // 0x82-0x9F are special windows chars 
			continue; // valid

		// else
		sText.SetAt(nChar, cReplace);
	}
}

BOOL CXmlItem::NameIs(LPCTSTR szName) const 
{ 
	return (m_sName == szName); 
}

LPCTSTR CXmlItem::GetName() const 
{ 
	return m_sName; 
}

LPCTSTR CXmlItem::GetValue() const 
{ 
	return m_sValue; 
}

int CXmlItem::GetNameLen() const 
{ 
	return m_sName.GetLength(); 
}

int CXmlItem::GetValueLen() const 
{ 
	return m_sValue.GetLength(); 
}

int CXmlItem::GetItemCount() const 
{ 
	return m_mapItems.GetCount(); 
}

int CXmlItem::GetValueI() const 
{ 
	return atoi(m_sValue); 
}

int CXmlItem::GetItemValueI(LPCTSTR szItemName, LPCTSTR szSubItemName) const 
{ 
	return atoi(GetItemValue(szItemName, szSubItemName)); 
}

double CXmlItem::GetValueF() const 
{ 
	return Misc::Atof(m_sValue); 
}

double CXmlItem::GetItemValueF(LPCTSTR szItemName, LPCTSTR szSubItemName) const 
{ 
	return Misc::Atof(GetItemValue(szItemName, szSubItemName)); 
}

void CXmlItem::DeleteAllItems() 
{ 
	Reset(); 
}

const CXmlItem* CXmlItem::GetParent() const 
{ 
	return m_pParent; 
}

const CXmlItem* CXmlItem::GetSibling() const 
{ 
	return m_pSibling; 
}

CXmlItem* CXmlItem::GetParent() 
{ 
	return m_pParent; 
}

CXmlItem* CXmlItem::GetSibling() 
{ 
	return m_pSibling; 
}

BOOL CXmlItem::IsAttribute(int nMaxAttribLen) const 
{ 
	return (GetValueLen() <= nMaxAttribLen && !m_mapItems.GetCount() && !IsCDATA()); 
}

CString CXmlItem::ToString(int nValue) 
{ 
	CString sValue; sValue.Format("%d", nValue); return sValue; 
}

CString CXmlItem::ToString(double dValue) 
{ 
	CString sValue; sValue.Format("%.8f", dValue); return sValue; 
}

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CXmlFile::CXmlFile(LPCTSTR szRootItemName) : m_xiRoot(NULL, szRootItemName)
{
}

CXmlFile::~CXmlFile()
{
	
}

BOOL CXmlFile::Load(LPCTSTR szFilePath, LPCTSTR szRootItemName, IXmlParse* pCallback)
{
	if (!szFilePath || !*szFilePath)
		return FALSE;
	
	if (GetFileHandle() != (HANDLE)CFile::hFileNull)
		Close();
	
	if (!szRootItemName && *(m_xiRoot.GetName()))
		szRootItemName = m_xiRoot.GetName();
	
	m_pCallback = pCallback;

	if (Open(szFilePath, XF_READ))
		return LoadEx(szRootItemName, pCallback);

	// else
	return FALSE;
	
/*
	CXmlDocumentWrapper doc;
	
	BOOL bRes = doc.Load(szFilePath);
	
	if (bRes && !ParseRootItem(szRootItemName, &doc))
		bRes = FALSE;
	
	return bRes;
*/
}

BOOL CXmlFile::Save(LPCTSTR szFilePath)
{
	if (!szFilePath || !*szFilePath)
		return FALSE;
	
	if (GetFileHandle() != (HANDLE)CFile::hFileNull)
		Close();
	
	if (Open(szFilePath, XF_WRITE))
	{
		BOOL bRes = SaveEx();
		Close();
		
		return bRes;
	}

	// error handling
	m_nFileError = GetLastError();
	
	return FALSE;
}

BOOL CXmlFile::Open(LPCTSTR szFilePath, XF_OPEN nOpenFlag)
{
	if (!szFilePath || !*szFilePath)
		return FALSE;
	
	if (GetFileHandle() != (HANDLE)CFile::hFileNull)
		Close();

	BOOL bRes = FALSE;
	
	switch (nOpenFlag)
	{
	case XF_READ:
		bRes = CFile::Open(szFilePath, CFile::shareDenyNone | CFile::modeRead);
		break;
		
	case XF_WRITE:
		bRes = CFile::Open(szFilePath, CFile::shareExclusive | CFile::modeWrite | CFile::modeCreate);
		break;
		
	case XF_READWRITE:
		bRes = CFile::Open(szFilePath, CFile::shareExclusive | CFile::modeReadWrite | 
			CFile::modeCreate | CFile::modeNoTruncate);
		break;
	}

	if (!bRes)
		m_nFileError = GetLastError();
	
	return bRes;
}

BOOL CXmlFile::SaveEx()
{
	if (GetFileHandle() == (HANDLE)CFile::hFileNull)
		return FALSE;
	
	BOOL bRes = FALSE;
	CString sXml;

	if (Export(sXml))
	{	
		try
		{
			Seek(0, CFile::begin); // move to start
			Write((const void*)(LPCTSTR)sXml, sXml.GetLength());
			::SetEndOfFile(GetFileHandle());

			bRes = TRUE;
		}
		catch (...)
		{
			m_nFileError = GetLastError();
		}
	}
	
	return bRes;
}

BOOL CXmlFile::LoadEx(LPCTSTR szRootItemName, IXmlParse* pCallback)
{
	m_nFileError = XFL_NONE; // reset
	
	if (GetFileHandle() == (HANDLE)CFile::hFileNull)
	{
		m_nFileError = ERROR_INVALID_HANDLE;
		return FALSE;
	}
	
	// concatenate entire file into one long string
	CString sLine;
	char* pFileContents = NULL;
	
	try
	{
		Seek(0, CFile::begin); // move to start
		
		// preallocate string to avoid excessive memory allocations
		DWORD dwLength = GetLength();
		pFileContents = new char[dwLength + 1];
		ZeroMemory(pFileContents, dwLength + 1);

		BOOL bContinue = TRUE;
		char* pFilePtr = pFileContents;
		
		while (bContinue)
		{
			DWORD nRead = Read(pFilePtr, dwLength);
			pFilePtr += nRead;
			bContinue = (nRead != dwLength);
		}

/*
		const UINT BUFLEN = 1024 * 100;
		char BUFFER[BUFLEN];
		BOOL bContinue = TRUE;
		char* pFilePtr = pFileContents;
		
		while (bContinue)
		{
			UINT nRead = Read(BUFFER, BUFLEN);
			
			if (nRead)
			{
				CopyMemory(pFilePtr, BUFFER, nRead);
				pFilePtr += BUFLEN;
			}
			
			bContinue = (nRead == BUFLEN);
		}
*/		

		pFileContents[dwLength] = 0;
	}
	catch (...)
	{
		m_nFileError = GetLastError();

		// cleanup
		delete [] pFileContents;
		m_pCallback = NULL;

		return FALSE;
	}
	
	if (!szRootItemName && m_xiRoot.GetNameLen())
		szRootItemName = m_xiRoot.GetName();
	
	m_pCallback = pCallback;
	
	LPCTSTR szFile = pFileContents;
	BOOL bRes = FALSE;
	
	try
	{
		CXmlDocumentWrapper doc;

		if (doc.IsValid())
		{
			if (!doc.LoadXML(szFile))
			{

⌨️ 快捷键说明

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