#include "stdafx.h" #include "XMLDocTree.h" #include #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif typedef struct XMLItem { TCHAR szKeyword[32]; //关键字 TCHAR szXData[128]; //扩展数据 XMLItem* pNextSiblingItem; XMLItem* pLastSiblingItem; XMLItem* pChildItem; XMLItem* pParentItem; }XMLITEM; CXMLDocTree::CXMLDocTree() { m_pRoot = NULL; } CXMLDocTree::~CXMLDocTree() { INT_PTR nSize = m_arBuffer.GetSize(); while(nSize > 0) { XMLItem* pItem = (XMLItem*)m_arBuffer.GetAt(0); if (pItem != NULL) { delete pItem; } m_arBuffer.RemoveAt(0); nSize = m_arBuffer.GetSize(); } } static void GetKeywordAndXData(CString& sText,CString& sKeyword,CString& sXData) { sKeyword = _T(""); sXData = _T(""); int nLen = sText.GetLength(); if (nLen > 0) { int nSpace = sText.Find(_T(' '),0); if (nSpace != -1) { sKeyword = sText.Mid(0,nSpace); if (nSpace < nLen - 1) { sXData = sText.Mid(nSpace + 1); } } else { sKeyword = sText; sXData = _T(""); } } } BOOL CXMLDocTree::SetXmlText(LPCTSTR pszXmlText) { if (pszXmlText == NULL) return FALSE; CString sXML = _T(""),sText = _T(""); CString sKeyword,sXData; CString sLine = _T(""); CString sXMLNew = pszXmlText; #ifdef UTF_8 sXML = pszXmlText; //UTF-8码转换为一般的字符串 WCHAR* pStrA = NULL; int nCount = MultiByteToWideChar(CP_UTF8 , 0 ,(char*)(LPCTSTR)sXML ,-1 ,NULL,0); pStrA = new WCHAR[nCount]; MultiByteToWideChar(CP_UTF8 ,0 ,(char*)(LPCTSTR)sXML, -1, pStrA , nCount); nCount = WideCharToMultiByte(CP_ACP,0,pStrA,-1,NULL,0,NULL,NULL); char* pStrB = new char[nCount]; WideCharToMultiByte(CP_ACP,0,pStrA,-1,pStrB,nCount,NULL,NULL); sXMLNew = pStrB; delete []pStrA; delete []pStrB; #endif int nFrL = sXMLNew.Find(_T('<'),0); int nFrR = sXMLNew.Find(_T('>'),0); int nToL = sXMLNew.ReverseFind(_T('<')); int nToR = sXMLNew.ReverseFind(_T('>')); if (nFrL != -1 && nFrR != -1 && nToL != -1 && nToR != -1) { sText = sXMLNew.Mid(nFrL + 1,nFrR - nFrL - 1); GetKeywordAndXData(sText,sKeyword,sXData); XMLItem* pRoot = new XMLItem; _tcscpy(pRoot->szKeyword,sKeyword); _tcscpy(pRoot->szXData,sXData); pRoot->pChildItem = NULL; pRoot->pNextSiblingItem = NULL; pRoot->pLastSiblingItem = NULL; pRoot->pParentItem = NULL; m_arBuffer.Add(pRoot); m_pRoot = (POSITION)pRoot; if (nFrR + 1 < sXMLNew.GetLength() - 1 && (nToL - nFrR - 1) > 0) { sLine = sXMLNew.Mid(nFrR + 1,nToL - nFrR - 1); MakeChildren(m_pRoot,sLine); } } return m_arBuffer.GetSize() > 0; } BOOL CXMLDocTree::Read(LPCTSTR pszFile) { CStdioFile file; if (!file.Open(pszFile,CFile::modeRead)) { return FALSE; } //1.读取xml; CString sXML = _T(""),sText = _T(""); CString sLine = _T(""); CString sKeyword,sXData; while(file.ReadString(sLine)) { sLine.TrimRight(); sLine.TrimLeft(); sXML += sLine; sLine = _T(""); } file.Close(); return SetXmlText(sXML); } // levelStack; TCHAR chX = 0; CString sText = _T(""); int nSta = sXMLText.Find(_T('<'),0); int nPos = 0,nNext = -1; if (nSta != -1) { nNext = nSta + 1; if (nNext < sXMLText.GetLength() - 1) { chX = sXMLText.GetAt(nNext); if (chX != _T('/')) { levelStack.push(1); nSta += 1; } } } if (levelStack.size() == 0) return -1; while(TRUE) { nPos = sXMLText.Find(_T('<'),nSta); if (nPos != -1) { //判断下一个是不是 / nNext = nPos + 1; if (nNext < sXMLText.GetLength() - 1) { chX = sXMLText.GetAt(nNext); if (chX == _T('/')) //是 / { levelStack.pop();// 弹出1 个 if (levelStack.size() < 1)// 如果到等级为1,则认为找到开始的匹配 = 1 push < = 2 push < = 3 push < = 2 pop < = 3 push < = 2 pop < = 1 pop < = 2 push < = 3 push = 2 pop = 1 pop = 0 pop 正好为1 */ BOOL CXMLDocTree::MakeChildren(POSITION pParent,const CString& sXMLText) { if (pParent == NULL) return FALSE; if (sXMLText.GetLength() == 0) return FALSE; CString sText,sKeyword,sXData; XMLItem* pParentItem = (XMLItem*)pParent; int nFrL = sXMLText.Find(_T('<'),0); int nFrR = sXMLText.Find(_T('>'),0); if (nFrL != -1 && nFrR != -1) { int nToL = sXMLText.Find(_T("szKeyword,sKeyword); _tcscpy(pChild->szXData,sXData); pChild->pChildItem = NULL; pChild->pNextSiblingItem = NULL; pChild->pLastSiblingItem = NULL; pChild->pParentItem = pParentItem; pParentItem->pChildItem = pChild; m_arBuffer.Add(pChild); //建立sibling 的 next; int nToR = sXMLText.Find(_T('>'),nToL + 1); if (nToR != -1) { sText = sXMLText.Mid(nToR + 1); CString sNext = sText; while(!sNext.IsEmpty()) { sNext = _T(""); MakeNextSiblingItem((POSITION&)pChild,sText,sNext); sText = sNext; } } } else //有内容,肯能有子[去掉空格有内容] { CString sText = sXMLText.Mid(nFrR + 1,nToL - nFrR - 1); sText.TrimLeft(); sText.TrimRight(); if (sText.IsEmpty()) //没有内容,说明没有子 { sText = sXMLText.Mid(nFrL + 1,nFrR - nFrL - 1); GetKeywordAndXData(sText,sKeyword,sXData); XMLItem* pChild = new XMLItem; _tcscpy(pChild->szKeyword,sKeyword); _tcscpy(pChild->szXData,sXData); pChild->pChildItem = NULL; pChild->pNextSiblingItem = NULL; pChild->pLastSiblingItem = NULL; pChild->pParentItem = pParentItem; pParentItem->pChildItem = pChild; m_arBuffer.Add(pChild); //建立sibling 的 next; int nToR = sXMLText.Find(_T('>'),nToL + 1); if (nToR != -1) { sText = sXMLText.Mid(nToR + 1); CString sNext = sText; while(!sNext.IsEmpty()) { sNext = _T(""); MakeNextSiblingItem((POSITION&)pChild,sText,sNext); sText = sNext; } } } else //中间有子 { //找到下一个平级的 szKeyword,sKeyword); _tcscpy(pChild->szXData,sXData); pChild->pChildItem = NULL; pChild->pNextSiblingItem = NULL; pChild->pLastSiblingItem = NULL; pChild->pParentItem = pParentItem; pParentItem->pChildItem = pChild; m_arBuffer.Add(pChild); //继续建立子 if (nToL - nFrR - 1 > 0) { sText = sXMLText.Mid(nFrR + 1,nToL - nFrR - 1); MakeChildren((POSITION)pChild,sText); } //继续建本级的sibling 级 int nToR = sXMLText.Find(_T('>'),nToL + 1); if (nToR != -1 && nToR + 1 < sXMLText.GetLength() - 1) { sText = sXMLText.Mid(nToR + 1); CString sNext = sText; while(!sNext.IsEmpty()) { sNext = _T(""); MakeNextSiblingItem((POSITION&)pChild,sText,sNext); sText = sNext; } } } } } } return FALSE; } BOOL CXMLDocTree::MakeNextSiblingItem(POSITION& pLast,const CString& sXMLText,CString& sNext) { sNext = _T(""); if (pLast == NULL) return FALSE; if (sXMLText.IsEmpty()) return FALSE; CString sText,sKeyword,sXData; XMLItem* pLastItem = (XMLItem*)pLast; int nFrL = sXMLText.Find(_T('<'),0); int nFrR = sXMLText.Find(_T('>'),0); if (nFrL != -1 && nFrR != -1) { int nToL = sXMLText.Find(_T("szKeyword,sKeyword); _tcscpy(pChild->szXData,sXData); pChild->pChildItem = NULL; pChild->pNextSiblingItem = NULL; pLastItem->pNextSiblingItem = pChild; pChild->pLastSiblingItem = pLastItem; pChild->pParentItem = pLastItem->pParentItem; m_arBuffer.Add(pChild); //建立sibling 的 next; int nToR = sXMLText.Find(_T('>'),nToL + 1); if (nToR != -1) { pLast = (POSITION)pChild; sNext = sXMLText.Mid(nToR + 1); return TRUE; } } else { CString sText = sXMLText.Mid(nFrR + 1,nToL - nFrR - 1); sText.TrimLeft(); sText.TrimRight(); if (sText.IsEmpty()) //没有内容,说明没有子 { sText = sXMLText.Mid(nFrL + 1,nFrR - nFrL - 1); GetKeywordAndXData(sText,sKeyword,sXData); XMLItem* pChild = new XMLItem; _tcscpy(pChild->szKeyword,sKeyword); _tcscpy(pChild->szXData,sXData); pChild->pChildItem = NULL; pChild->pNextSiblingItem = NULL; pLastItem->pNextSiblingItem = pChild; pChild->pLastSiblingItem = pLastItem; pChild->pParentItem = pLastItem->pParentItem; m_arBuffer.Add(pChild); //建立sibling 的 next; int nToR = sXMLText.Find(_T('>'),nToL + 1); if (nToR != -1) { pLast = (POSITION)pChild; sNext = sXMLText.Mid(nToR + 1); return TRUE; } } else //中间有子 { //找到下一个平级的 szKeyword,sKeyword); _tcscpy(pChild->szXData,sXData); pChild->pChildItem = NULL; pChild->pNextSiblingItem = NULL; pLastItem->pNextSiblingItem = pChild; pChild->pLastSiblingItem = pLastItem; pChild->pParentItem = pLastItem->pParentItem; m_arBuffer.Add(pChild); if (nToL - nFrR - 1 > 0) { sText = sXMLText.Mid(nFrR + 1,nToL - nFrR - 1); MakeChildren((POSITION)pChild,sText); } //继续建本级的sibling 级 int nToR = sXMLText.Find(_T('>'),nToL + 1); if (nToR != -1 && nToR + 1 < sXMLText.GetLength()) { pLast = (POSITION)pChild; sNext = sXMLText.Mid(nToR + 1); } } } } } return FALSE; } POSITION CXMLDocTree::GetRootItem() { return m_pRoot; } BOOL CXMLDocTree::GetKeyword(POSITION ps,CString& sKeyword) { if (ps != NULL) { sKeyword = ((XMLItem*)ps)->szKeyword; return TRUE; } return FALSE; } BOOL CXMLDocTree::GetValueText(POSITION ps,CString& sText) { if (ps != NULL) { sText = ((XMLItem*)ps)->szXData; return TRUE; } return FALSE; } BOOL CXMLDocTree::SetValueText(POSITION ps,CString& sText) { if (ps != NULL) { _tcscpy(((XMLItem*)ps)->szXData, sText); return TRUE; } return FALSE; } POSITION CXMLDocTree::GetNextSiblingItem(POSITION ps) { if (ps != NULL) { return (POSITION)((XMLItem*)ps)->pNextSiblingItem; } return NULL; } POSITION CXMLDocTree::GetPrevSiblingItem(POSITION ps) { if (ps != NULL) { return (POSITION)((XMLItem*)ps)->pLastSiblingItem; } return NULL; } POSITION CXMLDocTree::GetChildItem(POSITION ps) { if (ps != NULL) { return (POSITION)((XMLItem*)ps)->pChildItem; } return NULL; } POSITION CXMLDocTree::GetParentItem(POSITION ps) { if (ps != NULL) { return (POSITION)((XMLItem*)ps)->pParentItem; } return NULL; } BOOL CXMLDocTree::ItemHasChildren(POSITION ps) { if (ps != NULL) { return (((XMLItem*)ps)->pChildItem != NULL); } return FALSE; }