📄 xmlparser.cpp
字号:
} } } break; // If we found an end tag case eTokenTagEnd: // If we have node text then add this to the element if (lpszText) { cbTemp = (int)(token.pStr - lpszText); FindEndOfText(lpszText, &cbTemp); addText(fromXMLString(lpszText,cbTemp)); lpszText = NULL; } // Find the name of the end tag token = GetNextToken(pXML, &cbTemp, &type); // The end tag should be text if (type != eTokenText) { pXML->error = eXMLErrorMissingEndTagName; return FALSE; } lpszTemp = token.pStr; // After the end tag we should find a closing tag token = GetNextToken(pXML, &cbToken, &type); if (type != eTokenCloseTag) { pXML->error = eXMLErrorMissingEndTagName; return FALSE; } // We need to return to the previous caller. If the name // of the tag cannot be found we need to keep returning to // caller until we find a match if (myTagCompare(d->lpszName, lpszTemp) != 0)#ifdef STRICT_PARSING { pXML->error=eXMLErrorUnmatchedEndTag; return FALSE; }#else { pXML->error=eXMLErrorMissingEndTag; pXML->lpEndTag = lpszTemp; pXML->cbEndTag = cbTemp; }#endif // Return to the caller exactMemory(d); return TRUE; // If we found a clear (unformatted) token case eTokenClear: // 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; } if (!ParseClearTag(pXML, token.pClr)) { return FALSE; } break; // Errors... case eTokenCloseTag: /* '>' */ case eTokenShortHandClose: /* '/>' */ pXML->error = eXMLErrorUnexpectedToken; return FALSE; default: break; } break; // If we are inside a tag definition we need to search for attributes case eInsideTag: // Check what part of the attribute (name, equals, value) we // are looking for. switch(attrib) { // If we are looking for a new attribute case eAttribName: // Check what the current token type is switch(type) { // If the current type is text... // Eg. 'attribute' case eTokenText: // Cache the token then indicate that we are next to // look for the equals lpszTemp = token.pStr; cbTemp = cbToken; attrib = eAttribEquals; break; // If we found a closing tag... // Eg. '>' case eTokenCloseTag: // We are now outside the tag status = eOutsideTag; break; // If we found a short hand '/>' closing tag then we can // return to the caller case eTokenShortHandClose: exactMemory(d); return TRUE; // Errors... case eTokenQuotedText: /* '"SomeText"' */ case eTokenTagStart: /* '<' */ case eTokenTagEnd: /* '</' */ case eTokenEquals: /* '=' */ case eTokenDeclaration: /* '<?' */ case eTokenClear: pXML->error = eXMLErrorUnexpectedToken; return FALSE; default: break; } break; // If we are looking for an equals case eAttribEquals: // Check what the current token type is switch(type) { // If the current type is text... // Eg. 'Attribute AnotherAttribute' case eTokenText: // Add the unvalued attribute to the list addAttribute(stringDup(lpszTemp,cbTemp), NULL); // Cache the token then indicate. We are next to // look for the equals attribute lpszTemp = token.pStr; cbTemp = cbToken; break; // If we found a closing tag 'Attribute >' or a short hand // closing tag 'Attribute />' case eTokenShortHandClose: case eTokenCloseTag: // If we are a declaration element '<?' then we need // to remove extra closing '?' if it exists if (d->isDeclaration && (lpszTemp[cbTemp-1]) == _T('?')) { cbTemp--; } if (cbTemp) { // Add the unvalued attribute to the list addAttribute(stringDup(lpszTemp,cbTemp), NULL); } // If this is the end of the tag then return to the caller if (type == eTokenShortHandClose) { exactMemory(d); return TRUE; } // We are now outside the tag status = eOutsideTag; break; // If we found the equals token... // Eg. 'Attribute =' case eTokenEquals: // Indicate that we next need to search for the value // for the attribute attrib = eAttribValue; break; // Errors... case eTokenQuotedText: /* 'Attribute "InvalidAttr"'*/ case eTokenTagStart: /* 'Attribute <' */ case eTokenTagEnd: /* 'Attribute </' */ case eTokenDeclaration: /* 'Attribute <?' */ case eTokenClear: pXML->error = eXMLErrorUnexpectedToken; return FALSE; default: break; } break; // If we are looking for an attribute value case eAttribValue: // Check what the current token type is switch(type) { // If the current type is text or quoted text... // Eg. 'Attribute = "Value"' or 'Attribute = Value' or // 'Attribute = 'Value''. case eTokenText: case eTokenQuotedText: // If we are a declaration element '<?' then we need // to remove extra closing '?' if it exists if (d->isDeclaration && (token.pStr[cbToken-1]) == _T('?')) { cbToken--; } if (cbTemp) { // Add the valued attribute to the list if (type==eTokenQuotedText) { token.pStr++; cbToken-=2; } addAttribute(stringDup(lpszTemp,cbTemp),fromXMLString(token.pStr,cbToken)); } // Indicate we are searching for a new attribute attrib = eAttribName; break; // Errors... case eTokenTagStart: /* 'Attr = <' */ case eTokenTagEnd: /* 'Attr = </' */ case eTokenCloseTag: /* 'Attr = >' */ case eTokenShortHandClose: /* "Attr = />" */ case eTokenEquals: /* 'Attr = =' */ case eTokenDeclaration: /* 'Attr = <?' */ case eTokenClear: pXML->error = eXMLErrorUnexpectedToken; return FALSE; break; default: break; } } } } // If we failed to obtain the next token else { return FALSE; } }}// Count the number of lines and columns in an XML string.static void CountLinesAndColumns(LPCTSTR lpXML, int nUpto, XMLResults *pResults){ TCHAR ch; int n; assert(lpXML); assert(pResults); pResults->nLine = 1; pResults->nColumn = 1; for(n=0; n<nUpto; n++) { ch = lpXML[n]; assert(ch); if (ch == _T('\n')) { pResults->nLine++; pResults->nColumn = 1; } else pResults->nColumn++; }}// Parse XML and return the root element.XMLNode XMLNode::parseString(LPCTSTR lpszXML, LPCTSTR tag, XMLResults *pResults){ if (!lpszXML) { if (pResults) { pResults->error=eXMLErrorNoElements; pResults->nLine=0; pResults->nColumn=0; } return emptyXMLNode; } static struct ClearTag tags[] = { { _T("<![CDATA["), _T("]]>") }, { _T("<PRE>"), _T("</PRE>") }, { _T("<Script>"), _T("</Script>") }, { _T("<!--"), _T("-->") }, { _T("<!DOCTYPE"), _T(">") }, { NULL, NULL } }; enum XMLError error; XMLNode xnode(NULL,NULL,FALSE); struct XML xml={ NULL, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE , NULL}; xml.lpXML = lpszXML; xml.pClrTags = tags; // Create header element xnode.ParseXMLElement(&xml); error = xml.error; // If an error occurred if ((error==eXMLErrorNone)||(error==eXMLErrorMissingEndTag)) { if (tag&&_tcslen(tag)) { XMLNode nodeTmp; int i=0; while (i<xnode.nChildNode()) { nodeTmp=xnode.getChildNode(i); if (_tcsicmp(nodeTmp.getName(),tag)==0) break; if (nodeTmp.isDeclaration()) { xnode=nodeTmp; i=0; } else i++; } if (i<0) { if (pResults) { pResults->error=eXMLErrorTagNotFound; pResults->nLine=0; pResults->nColumn=0; } return emptyXMLNode; } xnode=nodeTmp; } } else { // Cleanup: this will destroy all the nodes xnode = emptyXMLNode; } // If we have been given somewhere to place results if (pResults) { pResults->error = error; // If we have an error if ((error!=eXMLErrorNone)&&(error!=eXMLErrorMissingEndTag)) { // Find which line and column it starts on. CountLinesAndColumns(xml.lpXML, xml.nIndex, pResults); } } return xnode;}XMLNode XMLNode::parseFile(const char *filename, LPCTSTR tag, XMLResults *pResults){ FILE *f=fopen(filename,"rb"); if (f==NULL) { if (pResults) { pResults->error=eXMLErrorFileNotFound; pResults->nLine=0; pResults->nColumn=0; } return emptyXMLNode; } fseek(f,0,SEEK_END); int l=ftell(f); fseek(f,0,SEEK_SET); char *buf=(char*)malloc(l+1); fread(buf,l,1,f); fclose(f); buf[l]=0;#ifdef WIN32#ifdef _UNICODE if (!IsTextUnicode(buf,mmin(l,10000),NULL)) { LPTSTR b2=(LPTSTR)malloc(l*2+2); MultiByteToWideChar(CP_ACP, // code page MB_PRECOMPOSED, // character-type options buf, // string to map l, // number of bytes in string b2, // wide-character buffer l*2+2); // size of buffer free(buf); buf=(char*)b2; }#else if (IsTextUnicode(buf,mmin(l,10000),NULL)) { l>>=1; LPTSTR b2=(LPTSTR)malloc(l+2); WideCharToMultiByte(CP_ACP, // code page 0, // performance and mapping flags (const WCHAR*)buf, // wide-character string l, // number of chars in string b2, // buffer for new string l+2, // size of buffer NULL, // default for unmappable chars NULL // set when default char used ); free(buf); buf=(char*)b2; }#endif#endif XMLNode x=parseString((LPTSTR)buf,tag,pResults); free(buf); return x;}XMLNode XMLNode::openFileHelper(const char *lpszXML, LPCTSTR tag){ XMLResults pResults; XMLNode xnode=XMLNode::parseFile(lpszXML, tag, &pResults); if (pResults.error != eXMLErrorNone) { printf( "XML Parsing error inside file '%s'.\n"#ifdef _UNICODE "Error: %S\n"#else "Error: %s\n"#endif "At line %i, column %i.\n",lpszXML, XMLNode::getError(pResults.error),pResults.nLine,pResults.nColumn); if (pResults.error==eXMLErrorTagNotFound) {#ifdef _UNICODE printf("Tag is '%S'.\n",tag);#else printf("Tag is '%s'.\n",tag);#endif } exit(255); } return xnode;}XMLNodeContents XMLNode::enumContents(int i){ XMLNodeContents c; if (!d) { c.type=eNodeNULL; return c; } c.type=(XMLElementType)(d->pOrder[i]&3); i=(d->pOrder[i])>>2; switch (c.type) { case eNodeChild: c.child = d->pChild[i]; break; case eNodeAttribute: c.attrib= d->pAttribute[i]; break; case eNodeText: c.text = d->pText[i]; break; case eNodeClear: c.clear = d->pClear[i]; break; default: break; } return c;}// private:void *XMLNode::enumContent(XMLNodeData *pEntry, int i, XMLElementType *nodeType){ XMLElementType j=(XMLElementType)(pEntry->pOrder[i]&3); *nodeType=j; i=(pEntry->pOrder[i])>>2; switch (j)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -