📄 xmlparser.cpp
字号:
*pType = eTokenTagStart; nSize = 1; } break; // Check to see if we have a short hand type end tag ('/>'). case _T('/'): // Peek at the next character to see if we have a short end tag '/>' chTemp = pXML->lpXML[pXML->nIndex]; // If we have a short hand end tag... if (chTemp == _T('>')) { // Set the type and ensure we point at the next character getNextChar(pXML); *pType = eTokenShortHandClose; nSize = 2; break; } // If we haven't found a short hand closing tag then drop into the // text process // Other characters default: nIsText = TRUE; } // If this is a TEXT node if (nIsText) { // Indicate we are dealing with text *pType = eTokenText; nSize = 1; nExit = FALSE; while((nExit == FALSE) && (ch = getNextChar(pXML))) { switch(ch) { // Break when we find white space case _T('\n'): case _T(' '): case _T('\t'): case _T('\r'): nExit = TRUE; break; // If we find a slash then this maybe text or a short hand end tag. case _T('/'): // Peek at the next character to see it we have short hand end tag chTemp = pXML->lpXML[pXML->nIndex]; // If we found a short hand end tag then we need to exit the loop if (chTemp == _T('>')) { pXML->nIndex--; // 03.02.2002 nExit = TRUE; } else { nSize++; } break; // Break when we find a terminator and decrement the index and // column count so that we are pointing at the right character // the next time we are called. case _T('<'): case _T('>'): case _T('='): pXML->nIndex--; nExit = TRUE; break; case 0: nExit = TRUE; break; default: nSize++; } } } *pcbToken = nSize; } else { // If we failed to obtain a valid character *pcbToken = 0; *pType = eTokenError; result.pStr=NULL; } return result;}// Parse XML errors into a user friendly string.LPCTSTR XMLNode::getError(XMLError error){ switch (error) { case eXMLErrorNone: return _T("No error"); case eXMLErrorMissingEndTag: return _T("Warning: Unmatched end tag"); case eXMLErrorEmpty: return _T("Error: No XML data"); case eXMLErrorFirstNotStartTag: return _T("Error: First token not start tag"); case eXMLErrorMissingTagName: return _T("Error: Missing start tag name"); case eXMLErrorMissingEndTagName: return _T("Error: Missing end tag name"); case eXMLErrorNoMatchingQuote: return _T("Error: Unmatched quote"); case eXMLErrorUnmatchedEndTag: return _T("Error: Unmatched end tag"); case eXMLErrorUnexpectedToken: return _T("Error: Unexpected token found"); case eXMLErrorInvalidTag: return _T("Error: Invalid tag found"); case eXMLErrorNoElements: return _T("Error: No elements found"); case eXMLErrorFileNotFound: return _T("Error: File not found"); case eXMLErrorTagNotFound: return _T("Error: First Tag not found"); }; return _T("Unknown");}// private:XMLNode::XMLNode(XMLNode *pParent, LPCTSTR lpszName, int isDeclaration){ d=(XMLNodeData*)malloc(sizeof(XMLNodeData)); d->ref_count=1; d->lpszName=lpszName; d->nChild= 0; d->nText = 0; d->nClear = 0; d->nAttribute = 0; d->isDeclaration = isDeclaration; d->pParent = pParent; d->pChild= NULL; d->pText= NULL; d->pClear= NULL; d->pAttribute= NULL; d->pOrder= NULL;}const int memoryIncrease=50;static void *myRealloc(void *p, int newsize, int memInc, int sizeofElem){ if (p==NULL) { return malloc(memInc*sizeofElem); } if ((newsize%memInc)==0) p=realloc(p,(newsize+memInc)*sizeofElem);// if (!p)
// {
// printf("XMLParser Error: Not enough memory! Aborting...\n"); exit(220);
// }
return p;}void XMLNode::addToOrder(int index, int type){ int n=nElement(); d->pOrder=(int*)myRealloc(d->pOrder,n+1,memoryIncrease*3,sizeof(int)); d->pOrder[n]=(index<<2)+type;}// Add a child node to the given element.XMLNode XMLNode::addChild(LPCTSTR lpszName, int isDeclaration){ if (!lpszName) return emptyXMLNode; int nc=d->nChild; d->pChild=(XMLNode*)myRealloc(d->pChild,(nc+1),memoryIncrease,sizeof(XMLNode)); d->pChild[nc].d=NULL; d->pChild[nc]=XMLNode(this,lpszName,isDeclaration); addToOrder(nc,eNodeChild); d->nChild++; return d->pChild[nc];}XMLNode XMLNode::createXMLTopNode() { return XMLNode(NULL,NULL,FALSE); }// Add an attribute to an element.XMLAttribute *XMLNode::addAttribute(LPCTSTR lpszName, LPCTSTR lpszValuev){ if (!lpszName) return &emptyXMLAttribute; int na=d->nAttribute; d->pAttribute=(XMLAttribute*)myRealloc(d->pAttribute,(na+1),memoryIncrease,sizeof(XMLAttribute)); XMLAttribute *pAttr=d->pAttribute+na; pAttr->lpszName = lpszName; pAttr->lpszValue = lpszValuev; addToOrder(na,eNodeAttribute); d->nAttribute++; return pAttr;}// Add text to the element.LPCTSTR XMLNode::addText(LPCTSTR lpszValue){ if (!lpszValue) return NULL; int nt=d->nText; d->pText=(LPCTSTR*)myRealloc(d->pText,(nt+1),memoryIncrease,sizeof(LPTSTR)); d->pText[nt]=lpszValue; addToOrder(nt,eNodeText); d->nText++; return d->pText[nt];}// Add clear (unformatted) text to the element.XMLClear *XMLNode::addClear(LPCTSTR lpszValue, LPCTSTR lpszOpen, LPCTSTR lpszClose){ if (!lpszValue) return &emptyXMLClear; int nc=d->nClear; d->pClear=(XMLClear *)myRealloc(d->pClear,(nc+1),memoryIncrease,sizeof(XMLClear)); XMLClear *pNewClear=d->pClear+nc; pNewClear->lpszValue = lpszValue; pNewClear->lpszOpenTag = lpszOpen; pNewClear->lpszCloseTag = lpszClose; addToOrder(nc,eNodeClear); d->nClear++; return pNewClear;}// Trim the end of the text to remove white space characters.static void FindEndOfText(LPCTSTR lpszToken, int *pcbText){ TCHAR ch; int cbText; assert(lpszToken); assert(pcbText); cbText = (*pcbText)-1; while(TRUE) { assert(cbText >= 0); ch = lpszToken[cbText]; switch(ch) { case _T('\r'): case _T('\n'): case _T('\t'): case _T(' '): cbText--; break; default: *pcbText = cbText+1; return; } }}// Duplicate a given string.LPTSTR stringDup(LPCTSTR lpszData, int cbData){ if (lpszData==NULL) return NULL; LPTSTR lpszNew; if (cbData==0) cbData=(int)_tcslen(lpszData); lpszNew = (LPTSTR)malloc((cbData+1) * sizeof(TCHAR)); if (lpszNew) { memcpy(lpszNew, lpszData, (cbData) * sizeof(TCHAR)); lpszNew[cbData] = (TCHAR)NULL; } return lpszNew;}// private:// Parse a clear (unformatted) type node.int XMLNode::ParseClearTag(void *px, void *pa){ XML *pXML=(XML *)px; ClearTag *pClear=(ClearTag *)pa; int cbTemp = 0; LPTSTR lpszTemp; LPCTSTR lpszXML = &pXML->lpXML[pXML->nIndex]; // Find the closing tag lpszTemp = _tcsstr(lpszXML, pClear->lpszClose); // Iterate through the tokens until we find the closing tag. if (lpszTemp) { // Cache the size and increment the index cbTemp = (int)(lpszTemp - lpszXML); pXML->nIndex += cbTemp; pXML->nIndex += (int)_tcslen(pClear->lpszClose); // Add the clear node to the current element addClear(stringDup(lpszXML,cbTemp), pClear->lpszOpen, pClear->lpszClose); return TRUE; } // If we failed to find the end tag pXML->error = eXMLErrorUnmatchedEndTag; return FALSE;}void XMLNode::exactMemory(XMLNodeData *d){
if (memoryIncrease==1) return; d->pOrder=(int*)realloc(d->pOrder,(d->nChild+d->nAttribute+d->nText+d->nClear)*sizeof(int)); d->pChild=(XMLNode*)realloc(d->pChild,d->nChild*sizeof(XMLNode)); d->pAttribute=(XMLAttribute*)realloc(d->pAttribute,d->nAttribute*sizeof(XMLAttribute)); d->pText=(LPCTSTR*)realloc(d->pText,d->nText*sizeof(LPTSTR)); d->pClear=(XMLClear *)realloc(d->pClear,d->nClear*sizeof(XMLClear));}// private:// Recursively parse an XML element.int XMLNode::ParseXMLElement(void *pa){ XML *pXML=(XML *)pa; int cbToken; enum TokenTypeTag type; NextToken token; LPCTSTR lpszTemp; int cbTemp; int nDeclaration; LPCTSTR lpszText = NULL; XMLNode pNew; enum Status status; // inside or outside a tag enum Attrib attrib = eAttribName; assert(pXML); // If this is the first call to the function if (pXML->nFirst) { // Assume we are outside of a tag definition pXML->nFirst = FALSE; status = eOutsideTag; } else { // If this is not the first call then we should only be called when inside a tag. status = eInsideTag; } // Iterate through the tokens in the document while(TRUE) { // Obtain the next token token = GetNextToken(pXML, &cbToken, &type); if (type != eTokenError) { // Check the current status switch(status) { // If we are outside of a tag definition case eOutsideTag: // Check what type of token we obtained switch(type) { // If we have found text or quoted text case eTokenText: case eTokenQuotedText: case eTokenEquals: if (!lpszText) { lpszText = token.pStr; } break; // If we found a start tag '<' and declarations '<?' case eTokenTagStart: case eTokenDeclaration: // Cache whether this new element is a declaration or not nDeclaration = type == eTokenDeclaration; // If we have node text then add this to the element if (lpszText) { cbTemp = (int)(token.pStr - lpszText); FindEndOfText(lpszText, &cbTemp); addText(stringDup(lpszText,cbTemp)); lpszText = NULL; } // Find the name of the tag token = GetNextToken(pXML, &cbToken, &type); // Return an error if we couldn't obtain the next token or // it wasnt text if (type != eTokenText) { pXML->error = eXMLErrorMissingTagName; return FALSE; } // If we found a new element which is the same as this // element then we need to pass this back to the caller..#ifdef APPROXIMATE_PARSING if (d->lpszName && myTagCompare(d->lpszName, token.pStr) == 0) { // Indicate to the caller that it needs to create a // new element. pXML->lpNewElement = token.pStr; pXML->cbNewElement = cbToken; return TRUE; } else#endif { // If the name of the new element differs from the name of // the current element we need to add the new element to // the current one and recurse pNew = addChild(stringDup(token.pStr,cbToken), nDeclaration); while (!pNew.isEmpty()) { // Callself to process the new node. If we return // FALSE this means we dont have any more // processing to do... if (!pNew.ParseXMLElement(pXML)) return FALSE; else { // If the call to recurse this function // evented in a end tag specified in XML then // we need to unwind the calls to this // function until we find the appropriate node // (the element name and end tag name must // match) if (pXML->cbEndTag) { // If we are back at the root node then we // have an unmatched end tag if (!d->lpszName) { pXML->error=eXMLErrorUnmatchedEndTag; return FALSE; } // If the end tag matches the name of this // element then we only need to unwind // once more... if (myTagCompare(d->lpszName, pXML->lpEndTag)==0) { pXML->cbEndTag = 0; } return TRUE; } else if (pXML->cbNewElement) { // If the call indicated a new element is to // be created on THIS element. // If the name of this element matches the // name of the element we need to create // then we need to return to the caller // and let it process the element. if (myTagCompare(d->lpszName, pXML->lpNewElement)==0) { return TRUE; } // Add the new element and recurse pNew = addChild(stringDup(pXML->lpNewElement,pXML->cbNewElement)); pXML->cbNewElement = 0; } else { // If we didn't have a new element to create pNew = emptyXMLNode; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -