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