//-----------------------------------------------------------------------------+ // Copyright (C), 1998-2007, SH Software Co. Ltd. // = FileName : XmlTree.cpp // = Version : ver1.0 // = Author : zjq // = CreateDate : // = Description: // = Maintainers: // //-----------------------------------------------------------------------------+ #include "StdAfx.h" #include "XmlTree.h" //内部类 class TXmlNode { friend class XmlTree; 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(""); return strXML; } XmlTree::XmlTree() { m_sDeclaration = _T(""); m_sComment = _T(""); DeleteAllItems(); } XmlTree::~XmlTree() { DeleteAllItems(); } CString XmlTree::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"); } TXmlNode* pNode = (TXmlNode*)posItem; strXML += pNode->GetXml(); return strXML; } return _T(""); } POSITION XmlTree::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; } // void XmlTree::SetDeclaration(LPCTSTR pszVer, LPCTSTR pszEncoding) { if (pszVer == NULL || pszEncoding == NULL) { m_sDeclaration = _T(""); } else { m_sDeclaration.Format(_T(""), pszVer, pszEncoding); } } CString XmlTree::GetDeclaration() const { return m_sDeclaration; } // void XmlTree::SetComment(LPCTSTR pszComment) { m_sComment = pszComment; } CString XmlTree::GetCommnet() const { return m_sComment; } BOOL XmlTree::SetItemText(POSITION posItem,LPCTSTR pszText) { TXmlNode* pNode = (TXmlNode*)posItem; if (pNode != NULL) { pNode->SetText(pszText); return TRUE; } return FALSE; } CString XmlTree::GetItemText(POSITION posItem) const { TXmlNode* pNode = (TXmlNode*)posItem; if (pNode != NULL) { return pNode->GetText(); } return CString(_T("")); } BOOL XmlTree::SetAttribute(POSITION posItem,LPCTSTR pszKey,LPCTSTR pszVal) { TXmlNode* pNode = (TXmlNode*)posItem; if (pNode != NULL) { pNode->SetAt(pszKey, pszVal); return TRUE; } return FALSE; } CString XmlTree::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 XmlTree::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 XmlTree::ItemHasChildren(POSITION posItem) const { TXmlNode* pNode = (TXmlNode*)posItem; if (pNode != NULL && pNode->m_posChild != NULL) { return TRUE; } return FALSE; } POSITION XmlTree::GetChildItem(POSITION posParent) const { TXmlNode* pNode = (TXmlNode*)posParent; if (pNode != NULL && pNode->m_posChild != NULL) { return pNode->m_posChild; } return NULL; } POSITION XmlTree::GetParentItem(POSITION posItem) const { TXmlNode* pNode = (TXmlNode*)posItem; if (pNode != NULL && pNode->m_posParent != NULL) { return pNode->m_posParent; } return NULL; } POSITION XmlTree::GetNextSiblingItem(POSITION posItem) const { TXmlNode* pNode = (TXmlNode*)posItem; if (pNode != NULL && pNode->m_posNext != NULL) { return pNode->m_posNext; } return NULL; } POSITION XmlTree::GetPrevSiblingItem(POSITION posItem) const { TXmlNode* pNode = (TXmlNode*)posItem; if (pNode != NULL && pNode->m_posPrevious != NULL) { return pNode->m_posPrevious; } return NULL; } BOOL XmlTree::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 XmlTree::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 XmlTree::GetCount() const { return m_lstItemPtrs.GetCount(); }