xmlfile.cpp

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

CPP
1,413
字号
				// try removing any bad chars
				CString sFile(szFile);
				FixInputString(sFile, szRootItemName);

				// then try again
				if (!doc.LoadXML(sFile))
					m_nFileError = XFL_BADMSXML;
			}

			// now read it into CXmlItem structures
			if (m_nFileError == XFL_NONE)
			{
				if (!ParseRootItem(szRootItemName, &doc))
					m_nFileError = XFL_MISSINGROOT;
				else
					bRes = TRUE;
			}
		}
	}
	catch (...)
	{
		m_nFileError = XFL_BADMSXML;
	}
	
	// cleanup
	delete [] pFileContents;
	m_pCallback = NULL;
	
	return bRes;
}

void CXmlFile::FixInputString(CString& sXml, LPCTSTR szRootItem)
{
	CXmlItem::ValidateString(sXml);

	// check for any other obvious problems
	if (szRootItem)
	{
		CString sRoot(szRootItem);
		sRoot = '<' + sRoot;

		int nRoot = sXml.Find(sRoot);
		int nHeader = sXml.Find("<?xml");

		if (nHeader > nRoot)
		{
			// what should we do?
			
/*
			// if there is another instance of szRootItem after the 
			// header tag then try deleting everything before the header
			// tag
			if (sXml.Find(sRoot, nHeader) != -1)
			{
				sXml = sXml.Right(nHeader);
			}
			else // try moving the header to the start
			{
				int nHeaderEnd = sXml.Find('>', nHeader) + 1;
				CString sHeader = sXml.Mid(nHeader, nHeaderEnd - nHeader);

				sXml = sHeader + sXml.Left(nHeader) + sXml.Right(nHeaderEnd);
			}
*/
		}
	}
	
}

BOOL CXmlFile::ParseRootItem(LPCTSTR szRootItemName, CXmlDocumentWrapper* pDoc)
{
	ASSERT (pDoc);
	
	m_xiRoot.Reset();
	
	CString sRootItem(szRootItemName), sItem;
	sRootItem.TrimLeft();
	sRootItem.TrimRight();
	
	// save off the header string
	// Valik - Change IXMLDOMNode* to IXMLDOMNodePtr to prevent an ambiguous symbol error (C2872) in VC 7.1
	MSXML2::IXMLDOMNodePtr pNode = pDoc->AsNode();
	CXmlNodeWrapper node(pNode);
	pNode->Release();
	
	if (0 != node.Name().CompareNoCase(sRootItem))
		return FALSE;
	
	m_sHeader = pDoc->GetHeader();
	
	// parse rest of file
	ParseItem(m_xiRoot, &node);
		
	return TRUE;
}

BOOL CXmlFile::ParseItem(CXmlItem& xi, CXmlNodeWrapper* pNode)
{
	int nNumAttrib = pNode->NumAttributes();
	
	for (int nAttrib = 0; nAttrib < nNumAttrib; nAttrib++)
	{
		CString sName(pNode->GetAttribName(nAttrib));
		CString sVal(pNode->GetAttribVal(nAttrib));
		
		xi.AddItem(sName, sVal);

		if (!ContinueParsing(sName, sVal))
			return TRUE;
	}
	
	int nNumNodes = pNode->NumNodes();
	
	for (int nNode = 0; nNode < nNumNodes; nNode++)
	{
		// Valik - Change IXMLDOMNode* to IXMLDOMNodePtr to prevent an ambiguous symbol error (C2872) in VC 7.1
		MSXML2::IXMLDOMNodePtr pChildNode = pNode->GetNode(nNode);
		CXmlNodeWrapper nodeChild(pChildNode);
		pChildNode->Release();
		
		CString sName(nodeChild.Name());
		CString sVal(nodeChild.GetText());
		
		// Valik - Fully qualify NODE_CDATA_SECTION to prevent an ambiguous symbol error (C2872) in VC 7.1
		BOOL bCData = (nodeChild.NodeTypeVal() == MSXML2::NODE_CDATA_SECTION);
		
		// if sName is empty then sVal relates to pNode
		if (!sName.IsEmpty())
		{
			CXmlItem* pXI = xi.AddItem(sName, sVal, bCData);
			
			if (!ContinueParsing(sName, sVal))
				return TRUE;
			
			ParseItem(*pXI, &nodeChild);
		}
		else
      {
			xi.SetValue(sVal);
			xi.SetCDATA(bCData);
      }
	}
	
	return TRUE;
}

void CXmlFile::Copy(const CXmlFile& file)
{
	m_xiRoot.Reset();
	m_xiRoot.Copy(file.m_xiRoot, TRUE);
}

BOOL CXmlFile::Export(CString& sOutput) const
{
	BOOL bRes = FALSE;
	sOutput.Empty();

	try
	{
		CXmlDocumentWrapper doc(m_sHeader, m_xiRoot.GetName());
		
		if (BuildDOM(&doc))
		{
			sOutput = doc.GetXML(TRUE);
			
			if (s_bFormatOutput && sOutput.GetLength())
				sOutput.Replace("><", ">\r\n<");

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

BOOL CXmlFile::BuildDOM(CXmlDocumentWrapper* pDoc) const
{
	if (!pDoc || !pDoc->IsValid())
		return FALSE;
	
	// Valik - Change IXMLDOMNode* to IXMLDOMNodePtr to prevent an ambiguous symbol error (C2872) in VC 7.1
	MSXML2::IXMLDOMNodePtr pNode = pDoc->AsNode();
	CXmlNodeWrapper node(pNode);
	pNode->Release();
	
	BOOL bRes = Export(&m_xiRoot, &node);
	
	return bRes;
}

BOOL CXmlFile::Transform(LPCTSTR szTransformPath, CString& sOutput, const CString& sEncoding) const
{
	CXmlDocumentWrapper doc(m_sHeader, m_xiRoot.GetName());
	
	if (BuildDOM(&doc))
	{
		sOutput = doc.Transform(szTransformPath);

		// encoding
		// note: the Transform function always returns UTF-16
		if (!sEncoding.IsEmpty())
			sOutput.Replace("UTF-16", sEncoding);
	}
	else
		sOutput.Empty();
	
	return TRUE;
}

BOOL CXmlFile::TransformToFile(LPCTSTR szTransformPath, LPCTSTR szOutputPath, const CString& sEncoding) const
{
	CString sOutput;
	
	if (Transform(szTransformPath, sOutput, sEncoding))
	{
		CFile output;
		
		if (output.Open(szOutputPath, CFile::modeCreate | CFile::modeWrite))
		{
			output.Write((void*)(LPCTSTR)sOutput, sOutput.GetLength());
			output.Close();
			
			return TRUE;
		}
	}
	
	return FALSE;
}

BOOL CXmlFile::Export(const CXmlItem* pItem, CXmlNodeWrapper* pNode) const
{
	// own value
	if (pItem->GetValueLen())
		pNode->SetText(pItem->GetValue());
	
	// attributes and items
	POSITION pos = pItem->GetFirstItemPos();
	int nNode = 0;
	
	while (pos)
	{
		const CXmlItem* pXIChild = pItem->GetNextItem(pos);
		ASSERT (pXIChild);
		
		CString sItem = pXIChild->GetName();
		
		if (pXIChild->IsAttribute())
		{
			ASSERT (!pXIChild->GetSibling());
			pNode->SetValue(sItem, pXIChild->GetValue());
		}
		else if (pXIChild->IsCDATA())
		{
			// create a named node to wrap the CDATA
			MSXML2::IXMLDOMNodePtr pChildNode = pNode->InsertNode(nNode++, (LPCTSTR)sItem);
			MSXML2::IXMLDOMCDATASectionPtr pCData = 
            pNode->ParentDocument()->createCDATASection(TOBSTRING(pXIChild->GetValue()));
			pChildNode->appendChild(pCData);
		}
		else // node
		{
			while (pXIChild)
			{
				// Valik - Change IXMLDOMNode* to IXMLDOMNodePtr to prevent an ambiguous symbol error (C2872) in VC 7.1
				MSXML2::IXMLDOMNodePtr pChildNode = pNode->InsertNode(nNode++, (LPCTSTR)sItem);
				CXmlNodeWrapper nodeChild(pChildNode);
				ASSERT (nodeChild.IsValid());
				pChildNode->Release();
				
				Export(pXIChild, &nodeChild);
				
				// siblings
				pXIChild = pXIChild->GetSibling();
			}
		}
	}
	
	return TRUE;
}

void CXmlFile::Trace() const 
{ 
#ifdef _DEBUG
	CString sXml;
	Export(sXml);
	
	// because the string might be long, output it in chunks of 255 chars
	int nPos = 0;
	
	while (nPos < sXml.GetLength())
	{
		OutputDebugString(sXml.Mid(nPos, 255));
		nPos += 255;
	}
#endif
}

void CXmlFile::Reset() 
{ 
	m_xiRoot.Reset(); 
}

int CXmlFile::GetItemCount() const 
{ 
	return m_xiRoot.GetItemCount(); 
}

void CXmlFile::Close() 
{ 
	CFile::Close(); 
}

int CXmlFile::GetLastFileError() 
{ 
	return m_nFileError; 
}

void CXmlFile::EnableFormattedOutput(BOOL bEnable) 
{ 
	s_bFormatOutput = bEnable; 
}

const CXmlItem* CXmlFile::Root() const 
{ 
	return &m_xiRoot; 
}

CXmlItem* CXmlFile::Root() 
{ 
	return &m_xiRoot; 
}

const CXmlItem* CXmlFile::GetItem(LPCTSTR szItemName) const 
{ 
	return m_xiRoot.GetItem(szItemName); 
} 

CXmlItem* CXmlFile::GetItem(LPCTSTR szItemName) 
{ 
	return m_xiRoot.GetItem(szItemName); 
}

const CXmlItem* CXmlFile::FindItem(LPCTSTR szItemName, LPCTSTR szItemValue, BOOL bSearchChildren) const
{ 
	return m_xiRoot.FindItem(szItemName, szItemValue, bSearchChildren); 
}

CXmlItem* CXmlFile::FindItem(LPCTSTR szItemName, LPCTSTR szItemValue, BOOL bSearchChildren)
{ 
	return m_xiRoot.FindItem(szItemName, szItemValue, bSearchChildren); 
}

const CXmlItem* CXmlFile::FindItem(LPCTSTR szItemName, int nItemValue, BOOL bSearchChildren) const
{ 
	return m_xiRoot.FindItem(szItemName, nItemValue, bSearchChildren); 
}

CXmlItem* CXmlFile::FindItem(LPCTSTR szItemName, int nItemValue, BOOL bSearchChildren)
{ 
	return m_xiRoot.FindItem(szItemName, nItemValue, bSearchChildren); 
}

const CXmlItem* CXmlFile::FindItem(LPCTSTR szItemName, double dItemValue, BOOL bSearchChildren) const
{ 
	return m_xiRoot.FindItem(szItemName, dItemValue, bSearchChildren); 
}

CXmlItem* CXmlFile::FindItem(LPCTSTR szItemName, double dItemValue, BOOL bSearchChildren)
{ 
	return m_xiRoot.FindItem(szItemName, dItemValue, bSearchChildren); 
}

CXmlItem* CXmlFile::AddItem(LPCTSTR szName, LPCTSTR szValue) 
{ 
	return m_xiRoot.AddItem(szName, szValue); 
}

CXmlItem* CXmlFile::AddItem(LPCTSTR szName, int nValue) 
{ 
	return m_xiRoot.AddItem(szName, nValue); 
}

CXmlItem* CXmlFile::AddItem(LPCTSTR szName, double dValue) 
{ 
	return m_xiRoot.AddItem(szName, dValue); 
}

BOOL CXmlFile::DeleteItem(CXmlItem* pXI) 
{ 
	return m_xiRoot.DeleteItem(pXI); 
}

LPCTSTR CXmlFile::GetItemValue(LPCTSTR szItemName, LPCTSTR szSubItemName) const 
{ 
	return m_xiRoot.GetItemValue(szItemName, szSubItemName); 
}

int CXmlFile::GetItemValueI(LPCTSTR szItemName, LPCTSTR szSubItemName) const 
{ 
	return m_xiRoot.GetItemValueI(szItemName, szSubItemName); 
}

double CXmlFile::GetItemValueF(LPCTSTR szItemName, LPCTSTR szSubItemName) const 
{ 
	return m_xiRoot.GetItemValueF(szItemName, szSubItemName); 
}

CXmlItem* CXmlFile::SetItemValue(LPCTSTR szName, LPCTSTR sValue, BOOL bCData)
{
	return m_xiRoot.SetItemValue(szName, sValue, bCData); 
}

CXmlItem* CXmlFile::SetItemValue(LPCTSTR szName, int nValue)
{
	return m_xiRoot.SetItemValue(szName, nValue); 
}

CXmlItem* CXmlFile::SetItemValue(LPCTSTR szName, double dValue)
{
	return m_xiRoot.SetItemValue(szName, dValue); 
}

CString CXmlFile::GetFilePath() const 
{ 
	return CFile::GetFilePath(); 
}

CString CXmlFile::GetFileName() const 
{ 
	return FileMisc::GetFileNameFromPath(GetFilePath());
}

const HANDLE CXmlFile::GetFileHandle() const 
{ 
	return (HANDLE)CFile::m_hFile; 
}

LPCTSTR CXmlFile::GetHeader() const 
{ 
	return m_sHeader; 
}

void CXmlFile::SetHeader(LPCTSTR szHeader) 
{ 
	m_sHeader = szHeader; m_sHeader.MakeLower(); 
}

void CXmlFile::SortItems(LPCTSTR szItemName, LPCTSTR szKeyName, BOOL bAscending)
{ 
	m_xiRoot.SortItems(szItemName, szKeyName, bAscending); 
}

void CXmlFile::SortItemsI(LPCTSTR szItemName, LPCTSTR szKeyName, BOOL bAscending)
{ 
	m_xiRoot.SortItemsI(szItemName, szKeyName, bAscending); 
}

void CXmlFile::SortItemsF(LPCTSTR szItemName, LPCTSTR szKeyName, BOOL bAscending)
{ 
	m_xiRoot.SortItemsF(szItemName, szKeyName, bAscending); 
}
	
BOOL CXmlFile::ContinueParsing(LPCTSTR szItem, LPCTSTR szValue) 
{ 
	return (!m_pCallback || m_pCallback->Continue(szItem, szValue)); 
}

⌨️ 快捷键说明

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