Files
envi-code/SourceCode/Code2026/tg_shs/shs_geLib/TXmlTree.cpp
T
2026-09-28 15:28:50 +08:00

547 lines
10 KiB
C++

//-----------------------------------------------------------------------------+
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
// = FileName : TXmlTree.cpp
// = Version : ver1.0
// = Author : xlc
// = CreateDate :
// = Description:
// = Maintainers:
//
//-----------------------------------------------------------------------------+
#include "StdAfx.h"
#include "TXmlTree.h"
//内部类
class TXmlNode
{
friend class TXmlTree;
public:
TXmlNode();
virtual ~TXmlNode();
void SetName(LPCTSTR pszName);
CString GetName() const;
void SetText(LPCTSTR pszText);
CString GetText() const;
//属性操作
void SetAt(LPCTSTR pszKey,LPCTSTR pszVal);
BOOL Lookup(LPCTSTR key, CString& rValue) const;
BOOL RemoveKey(LPCTSTR key);
void RemoveAll();
POSITION GetStartPosition() const;
void GetNextAssoc(POSITION& rNextPosition, CString& rKey, CString& rValue) const;
CString GetXml() const;
protected:
//数据
CMapStringToString m_mapKeyToVal; //属性
CString m_sName; //标签
CString m_sText; //文本
//前后关系
POSITION m_posPrevious;
POSITION m_posNext;
//上下关系
POSITION m_posParent;
POSITION m_posChild;
};
TXmlNode::TXmlNode()
{
m_sName = _T("");
m_sText = _T("");
m_posChild = NULL;
m_posParent = NULL;
m_posPrevious = NULL;
m_posNext = NULL;
}
TXmlNode::~TXmlNode()
{
}
void TXmlNode::SetName(LPCTSTR pszName)
{
m_sName = pszName;
}
CString TXmlNode::GetName() const
{
return m_sName;
}
void TXmlNode::SetText(LPCTSTR pszText)
{
m_sText = pszText;
}
CString TXmlNode::GetText() const
{
return m_sText;
}
//属性操作
void TXmlNode::SetAt(LPCTSTR pszKey,LPCTSTR pszVal)
{
m_mapKeyToVal.SetAt(pszKey, pszVal);
}
BOOL TXmlNode::Lookup(LPCTSTR key, CString& rValue) const
{
return m_mapKeyToVal.Lookup(key, rValue);
}
BOOL TXmlNode::RemoveKey(LPCTSTR key)
{
return m_mapKeyToVal.RemoveKey(key);
}
void TXmlNode::RemoveAll()
{
m_mapKeyToVal.RemoveAll();
}
POSITION TXmlNode::GetStartPosition() const
{
return m_mapKeyToVal.GetStartPosition();
}
void TXmlNode::GetNextAssoc(POSITION& rNextPosition, CString& rKey, CString& rValue) const
{
m_mapKeyToVal.GetNextAssoc(rNextPosition, rKey, rValue);
}
CString TXmlNode::GetXml() const
{
if (m_sName.IsEmpty())
{
return _T("");
}
CString strXML;
strXML += _T("\n<") +m_sName;
CString strKey;
CString strVal;
POSITION pos = GetStartPosition();
while (pos != NULL)
{
GetNextAssoc(pos, strKey, strVal);
strXML += _T(" ") + strKey + _T(" = \"") + strVal + _T("\"");
}
strXML += _T(">") + m_sText;
if(m_posChild != NULL)
{
TXmlNode* pNodeChild = (TXmlNode*)m_posChild;
// 遍历前节点
POSITION posPre = pNodeChild->m_posPrevious;
CString strNode;
CStringArray strArray;
while (posPre != NULL)
{
strNode = ((TXmlNode*)posPre)->GetXml();
strArray.Add(strNode);
posPre = ((TXmlNode*)posPre)->m_posPrevious;
}
for (int i = strArray.GetSize() - 1; i >= 0; i--)
{
strXML += strArray[i];
}
// 当前节点
strXML += pNodeChild->GetXml();
// 遍历后节点
POSITION posNext = pNodeChild->m_posNext;
while (posNext != NULL)
{
strXML += ((TXmlNode*)posNext)->GetXml();
posNext = ((TXmlNode*)posNext)->m_posNext;
}
strXML += _T("\n");
}
strXML += _T("</") + m_sName + _T(">");
return strXML;
}
TXmlTree::TXmlTree()
{
m_sDeclaration = _T("");
m_sComment = _T("");
DeleteAllItems();
}
TXmlTree::~TXmlTree()
{
DeleteAllItems();
}
CString TXmlTree::GetXml()
{
if (GetCount() <= 0)
{
return _T("");
}
POSITION posItem = GetRootItem();
if (posItem != NULL)
{
CString strXML;
if (!m_sDeclaration.IsEmpty())
{
strXML += m_sDeclaration;
}
if (!m_sComment.IsEmpty())
{
strXML += _T("\n<!-- ") + m_sComment + _T(" -->");
}
TXmlNode* pNode = (TXmlNode*)posItem;
strXML += pNode->GetXml();
return strXML;
}
return _T("");
}
POSITION TXmlTree::GetRootItem()
{
if (GetCount() <= 0)
{
return NULL;
}
POSITION rootItem=NULL;
POSITION posItem = (POSITION)m_lstItemPtrs.GetHead();
while(posItem != NULL)
{
rootItem = posItem;
posItem = GetParentItem(rootItem);
}
return rootItem;
}
//<?xml version="1.0" encoding="UTF-8"?>
void TXmlTree::SetDeclaration(LPCTSTR pszVer, LPCTSTR pszEncoding)
{
if (pszVer == NULL || pszEncoding == NULL)
{
m_sDeclaration = _T("");
}
else
{
m_sDeclaration.Format(_T("<?xml version=\"%s\" encoding=\"%s\"?>"), pszVer, pszEncoding);
}
}
CString TXmlTree::GetDeclaration() const
{
return m_sDeclaration;
}
//<!-- Copy text, comments and processing instructions. -->
void TXmlTree::SetComment(LPCTSTR pszComment)
{
m_sComment = pszComment;
}
CString TXmlTree::GetCommnet() const
{
return m_sComment;
}
BOOL TXmlTree::SetItemText(POSITION posItem,LPCTSTR pszText)
{
TXmlNode* pNode = (TXmlNode*)posItem;
if (pNode != NULL)
{
pNode->SetText(pszText);
return TRUE;
}
return FALSE;
}
CString TXmlTree::GetItemText(POSITION posItem) const
{
TXmlNode* pNode = (TXmlNode*)posItem;
if (pNode != NULL)
{
return pNode->GetText();
}
return CString(_T(""));
}
BOOL TXmlTree::SetAttribute(POSITION posItem,LPCTSTR pszKey,LPCTSTR pszVal)
{
TXmlNode* pNode = (TXmlNode*)posItem;
if (pNode != NULL)
{
pNode->SetAt(pszKey, pszVal);
return TRUE;
}
return FALSE;
}
CString TXmlTree::GetAttribute(POSITION posItem,LPCTSTR pszKey) const
{
TXmlNode* pNode = (TXmlNode*)posItem;
if (pNode != NULL)
{
CString strVal;
pNode->Lookup(pszKey, strVal);
return strVal;
}
return CString(_T(""));
}
POSITION TXmlTree::Insert(LPCTSTR pszItem,POSITION posParent,POSITION posInsertAfter)
{
TXmlNode* pNodeParent = (TXmlNode*)posParent;
TXmlNode* pNodeInsertAfter = (TXmlNode*)posInsertAfter;
if (pNodeParent != NULL)
{
// 新节点与插入节点的父节点不一致时不插入
if (pNodeInsertAfter && pNodeInsertAfter->m_posParent != posParent)
{
return NULL;
}
TXmlNode* pNodeNew = new TXmlNode();
pNodeNew->SetName(pszItem);
pNodeNew->m_posParent = posParent;
if (pNodeParent->m_posChild != NULL) //有孩子节点
{
if (pNodeInsertAfter == NULL) //没有插入节点
{
POSITION posNextItem = pNodeParent->m_posChild;
POSITION posInsertItem = NULL;
while(posNextItem != NULL)
{
posInsertItem = posNextItem;
posNextItem = ((TXmlNode*)posNextItem)->m_posNext;
}
pNodeNew->m_posPrevious = posInsertItem;
((TXmlNode*)posInsertItem)->m_posNext = (POSITION)pNodeNew;
}
else
{
POSITION posNextItem = pNodeInsertAfter->m_posNext;
if (posNextItem == NULL) //节点末尾
{
pNodeNew->m_posPrevious = posInsertAfter;
pNodeInsertAfter->m_posNext = (POSITION)pNodeNew;
}
else
{
((TXmlNode*)posNextItem)->m_posPrevious = (POSITION)pNodeNew;
pNodeInsertAfter->m_posNext = (POSITION)pNodeNew;
pNodeNew->m_posPrevious = posInsertAfter;
pNodeNew->m_posNext = posNextItem;
}
}
}
else
{
pNodeParent->m_posChild = (POSITION)pNodeNew;
}
m_lstItemPtrs.AddTail(pNodeNew);
return (POSITION)pNodeNew;
}
else
{
if (GetCount() == 0) //插入根节点
{
TXmlNode* pNodeNew = new TXmlNode();
pNodeNew->SetName(pszItem);
m_lstItemPtrs.AddTail(pNodeNew);
return (POSITION)pNodeNew;
}
}
return NULL;
}
BOOL TXmlTree::ItemHasChildren(POSITION posItem) const
{
TXmlNode* pNode = (TXmlNode*)posItem;
if (pNode != NULL && pNode->m_posChild != NULL)
{
return TRUE;
}
return FALSE;
}
POSITION TXmlTree::GetChildItem(POSITION posParent) const
{
TXmlNode* pNode = (TXmlNode*)posParent;
if (pNode != NULL && pNode->m_posChild != NULL)
{
return pNode->m_posChild;
}
return NULL;
}
POSITION TXmlTree::GetParentItem(POSITION posItem) const
{
TXmlNode* pNode = (TXmlNode*)posItem;
if (pNode != NULL && pNode->m_posParent != NULL)
{
return pNode->m_posParent;
}
return NULL;
}
POSITION TXmlTree::GetNextSiblingItem(POSITION posItem) const
{
TXmlNode* pNode = (TXmlNode*)posItem;
if (pNode != NULL && pNode->m_posNext != NULL)
{
return pNode->m_posNext;
}
return NULL;
}
POSITION TXmlTree::GetPrevSiblingItem(POSITION posItem) const
{
TXmlNode* pNode = (TXmlNode*)posItem;
if (pNode != NULL && pNode->m_posPrevious != NULL)
{
return pNode->m_posPrevious;
}
return NULL;
}
BOOL TXmlTree::DeleteItem(POSITION posItem)
{
if (posItem == NULL)
{
return FALSE;
}
TXmlNode* pNodeItem = (TXmlNode*)posItem;
POSITION posPreItem = GetPrevSiblingItem(posItem);
POSITION posNextItem = GetNextSiblingItem(posItem);
POSITION posParent = GetParentItem(posItem);
if (posParent == NULL) //删除根节点时全部删除
{
DeleteAllItems();
return TRUE;
}
else if (((TXmlNode*)posParent)->m_posChild == posItem) //孩子节点为当前节点
{
// 修改节点上下连接关系
if (posPreItem != NULL)
{
((TXmlNode*)posParent)->m_posChild = posPreItem;
}
else
{
((TXmlNode*)posParent)->m_posChild = posNextItem;
}
}
//修改节点前后连接关系
if (posPreItem == NULL && posNextItem == NULL) //删除唯一孩子结点
{
}
else if (posPreItem == NULL) //删除头节点
{
((TXmlNode*)posNextItem)->m_posPrevious = NULL;
}
else if (posNextItem == NULL) //删除尾节点
{
((TXmlNode*)posPreItem)->m_posNext = NULL;
}
else //删除头节点
{
((TXmlNode*)posPreItem)->m_posNext = posNextItem;
((TXmlNode*)posNextItem)->m_posPrevious = posPreItem;
}
//遍历孩子节点
if (pNodeItem->m_posChild != NULL)
{
POSITION posChild = GetChildItem(posItem);
posPreItem = GetPrevSiblingItem(posChild);
posNextItem = GetNextSiblingItem(posChild);
POSITION pos = NULL;
while (posPreItem != NULL) //删除孩子节点前的兄弟节点
{
pos = posPreItem;
posPreItem = GetPrevSiblingItem(pos);
DeleteItem(pos);
}
DeleteItem(posChild); //删除孩子节点
while (posNextItem != NULL) //删除孩子节点后的兄弟节点
{
pos = posNextItem;
posNextItem = GetNextSiblingItem(pos);
DeleteItem(pos);
}
pNodeItem->m_posChild = NULL;
}
POSITION pos = m_lstItemPtrs.Find(pNodeItem);
TXmlNode* pNode = (TXmlNode*)m_lstItemPtrs.GetAt(pos);
if (pNode)
{
delete pNode;
}
m_lstItemPtrs.RemoveAt(pos);
return TRUE;
}
BOOL TXmlTree::DeleteAllItems()
{
POSITION posItem = NULL;
for (int i = 0; i < m_lstItemPtrs.GetCount(); i++)
{
posItem = m_lstItemPtrs.FindIndex(i);
TXmlNode* pNode = (TXmlNode*)m_lstItemPtrs.GetAt(posItem);
if (pNode)
{
delete pNode;
}
}
m_lstItemPtrs.RemoveAll();
return TRUE;
}
UINT TXmlTree::GetCount() const
{
return m_lstItemPtrs.GetCount();
}