📄 xmlparser.cpp
字号:
{ // If we are looking for a new attribute case eAttribName: // Check what the current token type is switch(xtype) { // 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; pXML->lpszText=pXML->lpXML+pXML->nIndex; break; // If we found a short hand '/>' closing tag then we can // return to the caller case eTokenShortHandClose: exactMemory(d); pXML->lpszText=pXML->lpXML+pXML->nIndex; 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(xtype) { // If the current type is text... // Eg. 'Attribute AnotherAttribute' case eTokenText: // Add the unvalued attribute to the list addAttribute_priv(MEMORYINCREASE,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 pXML->lpszText=pXML->lpXML+pXML->nIndex; if (d->isDeclaration && (lpszTemp[cbTemp-1]) == _X('?')) { cbTemp--; } if (cbTemp) { // Add the unvalued attribute to the list addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp), NULL); } // If this is the end of the tag then return to the caller if (xtype == 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(xtype) { // 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]) == _X('?')) { cbToken--; } if (cbTemp) { // Add the valued attribute to the list if (xtype==eTokenQuotedText) { token.pStr++; cbToken-=2; } XMLSTR attrVal=(XMLSTR)token.pStr; if (attrVal) { attrVal=fromXMLString(attrVal,cbToken,pXML); if (!attrVal) return FALSE; } addAttribute_priv(MEMORYINCREASE,stringDup(lpszTemp,cbTemp),attrVal); } // 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 { if ((!d->isDeclaration)&&(d->pParent)) {#ifdef STRICT_PARSING pXML->error=eXMLErrorUnmatchedEndTag;#else pXML->error=eXMLErrorMissingEndTag;#endif pXML->nIndexMissigEndTag=pXML->nIndex; } maybeAddTxT(pXML,pXML->lpXML+pXML->nIndex); return FALSE; } }}// Count the number of lines and columns in an XML string.static void CountLinesAndColumns(XMLCSTR lpXML, int nUpto, XMLResults *pResults){ XMLCHAR ch; assert(lpXML); assert(pResults); struct XML xml={ lpXML,lpXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE }; pResults->nLine = 1; pResults->nColumn = 1; while (xml.nIndex<nUpto) { ch = getNextChar(&xml); if (ch != _X('\n')) pResults->nColumn++; else { pResults->nLine++; pResults->nColumn=1; } }}// Parse XML and return the root element.XMLNode XMLNode::parseString(XMLCSTR lpszXML, XMLCSTR tag, XMLResults *pResults){ if (!lpszXML) { if (pResults) { pResults->error=eXMLErrorNoElements; pResults->nLine=0; pResults->nColumn=0; } return emptyXMLNode; } XMLNode xnode(NULL,NULL,FALSE); struct XML xml={ lpszXML, lpszXML, 0, 0, eXMLErrorNone, NULL, 0, NULL, 0, TRUE }; // Create header element xnode.ParseXMLElement(&xml); enum XMLError error = xml.error; if (!xnode.nChildNode()) error=eXMLErrorNoXMLTagFound; if ((xnode.nChildNode()==1)&&(xnode.nElement()==1)) xnode=xnode.getChildNode(); // skip the empty node // If no error occurred if ((error==eXMLErrorNone)||(error==eXMLErrorMissingEndTag)||(error==eXMLErrorNoXMLTagFound)) { XMLCSTR name=xnode.getName(); if (tag&&xstrlen(tag)&&((!name)||(xstricmp(xnode.getName(),tag)))) { XMLNode nodeTmp; int i=0; while (i<xnode.nChildNode()) { nodeTmp=xnode.getChildNode(i); if (xstricmp(nodeTmp.getName(),tag)==0) break; if (nodeTmp.isDeclaration()) { xnode=nodeTmp; i=0; } else i++; } if (i>=xnode.nChildNode()) { if (pResults) { pResults->error=eXMLErrorFirstTagNotFound; 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) { if (error==eXMLErrorMissingEndTag) xml.nIndex=xml.nIndexMissigEndTag; // Find which line and column it starts on. CountLinesAndColumns(xml.lpXML, xml.nIndex, pResults); } } return xnode;}XMLNode XMLNode::parseFile(XMLCSTR filename, XMLCSTR tag, XMLResults *pResults){ if (pResults) { pResults->nLine=0; pResults->nColumn=0; } FILE *f=xfopen(filename,_X("rb")); if (f==NULL) { if (pResults) pResults->error=eXMLErrorFileNotFound; return emptyXMLNode; } fseek(f,0,SEEK_END); int l=ftell(f),headerSz=0; if (!l) { if (pResults) pResults->error=eXMLErrorEmpty; fclose(f); return emptyXMLNode; } fseek(f,0,SEEK_SET); unsigned char *buf=(unsigned char*)malloc(l+4); fread(buf,l,1,f); fclose(f); buf[l]=0;buf[l+1]=0;buf[l+2]=0;buf[l+3]=0;#ifdef _XMLWIDECHAR if (guessWideCharChars) { if (!myIsTextWideChar(buf,l)) { if ((buf[0]==0xef)&&(buf[1]==0xbb)&&(buf[2]==0xbf)) headerSz=3; XMLSTR b2=myMultiByteToWideChar((const char*)(buf+headerSz)); free(buf); buf=(unsigned char*)b2; headerSz=0; } else { if ((buf[0]==0xef)&&(buf[1]==0xff)) headerSz=2; if ((buf[0]==0xff)&&(buf[1]==0xfe)) headerSz=2; } }#else if (guessWideCharChars) { if (myIsTextWideChar(buf,l)) { l/=sizeof(wchar_t); if ((buf[0]==0xef)&&(buf[1]==0xff)) headerSz=2; if ((buf[0]==0xff)&&(buf[1]==0xfe)) headerSz=2; char *b2=myWideCharToMultiByte((const wchar_t*)(buf+headerSz)); free(buf); buf=(unsigned char*)b2; headerSz=0; } else { if ((buf[0]==0xef)&&(buf[1]==0xbb)&&(buf[2]==0xbf)) headerSz=3; } }#endif if (!buf) { if (pResults) pResults->error=eXMLErrorCharConversionError; return emptyXMLNode; } XMLNode x=parseString((XMLSTR)(buf+headerSz),tag,pResults); free(buf); return x;}static inline void charmemset(XMLSTR dest,XMLCHAR c,int l) { while (l--) *(dest++)=c; }// private:// Creates an user friendly XML string from a given element with// appropriate white space and carriage returns.//// This recurses through all subnodes then adds contents of the nodes to the// string.int XMLNode::CreateXMLStringR(XMLNodeData *pEntry, XMLSTR lpszMarker, int nFormat){ int nResult = 0; int cb; int cbElement; int nChildFormat=-1; int nElementI=pEntry->nChild+pEntry->nText+pEntry->nClear; int i,j; assert(pEntry);#define LENSTR(lpsz) (lpsz ? xstrlen(lpsz) : 0) // If the element has no name then assume this is the head
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -