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 + -
显示快捷键?