📄 xmlparser.cpp
字号:
{ case eNodeChild: return pEntry->pChild[i].d; case eNodeAttribute: return pEntry->pAttribute+i; case eNodeText: return (void*)(pEntry->pText[i]); case eNodeClear: return pEntry->pClear+i; default: break; } return NULL;}// private:int XMLNode::nElement(XMLNodeData *pEntry){ return pEntry->nChild+pEntry->nText+pEntry->nClear+pEntry->nAttribute;}static inline void charmemset(LPTSTR dest,TCHAR 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, LPTSTR lpszMarker, int nFormat){ int nResult = 0; int cb; int cbElement; int nIndex; int nChildFormat=-1; int bHasChildren=FALSE; int i; XMLAttribute * pAttr; assert(pEntry);#define LENSTR(lpsz) (lpsz ? _tcslen(lpsz) : 0) // If the element has no name then assume this is the head node. cbElement = (int)LENSTR(pEntry->lpszName); if (cbElement) { // "<elementname " cb = nFormat == -1 ? 0 : nFormat; if (lpszMarker) { if (cb) charmemset(lpszMarker, INDENTCHAR, sizeof(TCHAR)*cb); nResult = cb; lpszMarker[nResult++]=_T('<'); if (pEntry->isDeclaration) lpszMarker[nResult++]=_T('?'); _tcscpy(&lpszMarker[nResult], pEntry->lpszName); nResult+=cbElement; lpszMarker[nResult++]=_T(' '); } else { nResult+=cbElement+2+cb; if (pEntry->isDeclaration) nResult++; } // Enumerate attributes and add them to the string nIndex = pEntry->nAttribute; pAttr=pEntry->pAttribute; for (i=0; i<nIndex; i++) { // "Attrib cb = (int)LENSTR(pAttr->lpszName); if (cb) { if (lpszMarker) _tcscpy(&lpszMarker[nResult], pAttr->lpszName); nResult += cb; // "Attrib=Value " cb = (int)lengthXMLString(pAttr->lpszValue); if (lpszMarker) { lpszMarker[nResult]=_T('='); lpszMarker[nResult+1]=_T('"'); if (cb) toXMLString(&lpszMarker[nResult+2],pAttr->lpszValue); lpszMarker[nResult+cb+2]=_T('"'); } nResult+=cb+3; if (lpszMarker) lpszMarker[nResult] = _T(' '); nResult++; } pAttr++; } bHasChildren=(pEntry->nAttribute!=nElement(pEntry)); if (pEntry->isDeclaration) { if (lpszMarker) { lpszMarker[nResult-1]=_T('?'); lpszMarker[nResult]=_T('>'); } nResult++; if (nFormat!=-1) { if (lpszMarker) lpszMarker[nResult]=_T('\n'); nResult++; } } else // If there are child nodes we need to terminate the start tag if (bHasChildren) { if (lpszMarker) lpszMarker[nResult-1]=_T('>'); if (nFormat!=-1) { if (lpszMarker) lpszMarker[nResult]=_T('\n'); nResult++; } } else nResult--; } // Calculate the child format for when we recurse. This is used to // determine the number of spaces used for prefixes. if (nFormat!=-1) { if (cbElement&&(!pEntry->isDeclaration)) nChildFormat=nFormat+1; else nChildFormat=nFormat; } // Enumerate through remaining children nIndex = nElement(pEntry); XMLElementType nodeType; void *pChild; for (i=0; i<nIndex; i++) { pChild=enumContent(pEntry, i, &nodeType); switch(nodeType) { // Text nodes case eNodeText: // "Text" cb = (int)lengthXMLString((LPTSTR)pChild); if (cb) { if (nFormat!=-1) { if (lpszMarker) { charmemset(&lpszMarker[nResult],INDENTCHAR,sizeof(TCHAR)*(nFormat + 1)); toXMLString(&lpszMarker[nResult+nFormat+1],(LPTSTR)pChild); lpszMarker[nResult+nFormat+1+cb]=_T('\n'); } nResult+=cb+nFormat+2; } else { if (lpszMarker) toXMLString(&lpszMarker[nResult], (LPTSTR)pChild); nResult += cb; } } break; // Clear type nodes case eNodeClear: // "OpenTag" cb = (int)LENSTR(((XMLClear*)pChild)->lpszOpenTag); if (cb) { if (nFormat!=-1) { if (lpszMarker) { charmemset(&lpszMarker[nResult], INDENTCHAR, sizeof(TCHAR)*(nFormat + 1)); _tcscpy(&lpszMarker[nResult+nFormat+1], ((XMLClear*)pChild)->lpszOpenTag); } nResult+=cb+nFormat+1; } else { if (lpszMarker)_tcscpy(&lpszMarker[nResult], ((XMLClear*)pChild)->lpszOpenTag); nResult += cb; } } // "OpenTag Value" cb = (int)LENSTR(((XMLClear*)pChild)->lpszValue); if (cb) { if (lpszMarker) _tcscpy(&lpszMarker[nResult], ((XMLClear*)pChild)->lpszValue); nResult += cb; } // "OpenTag Value CloseTag" cb = (int)LENSTR(((XMLClear*)pChild)->lpszCloseTag); if (cb) { if (lpszMarker) _tcscpy(&lpszMarker[nResult], ((XMLClear*)pChild)->lpszCloseTag); nResult += cb; } if (nFormat!=-1) { if (lpszMarker) lpszMarker[nResult] = _T('\n'); nResult++; } break; // Element nodes case eNodeChild: // Recursively add child nodes nResult += CreateXMLStringR((XMLNodeData*)pChild, lpszMarker ? lpszMarker + nResult : 0, nChildFormat); break; default: break; } } if ((cbElement)&&(!pEntry->isDeclaration)) { // If we have child entries we need to use long XML notation for // closing the element - "<elementname>blah blah blah</elementname>" if (bHasChildren) { // "</elementname>\0" if (lpszMarker) { if (nFormat != -1) { if (nFormat) { charmemset(&lpszMarker[nResult], INDENTCHAR,sizeof(TCHAR)*nFormat); nResult+=nFormat; } } _tcscpy(&lpszMarker[nResult], _T("</")); nResult += 2; _tcscpy(&lpszMarker[nResult], pEntry->lpszName); nResult += cbElement; if (nFormat == -1) { _tcscpy(&lpszMarker[nResult], _T(">")); nResult++; } else { _tcscpy(&lpszMarker[nResult], _T(">\n")); nResult+=2; } } else { if (nFormat != -1) nResult+=cbElement+4+nFormat; else nResult+=cbElement+3; } } else { // If there are no children we can use shorthand XML notation - // "<elementname/>" // "/>\0" if (lpszMarker) { if (nFormat == -1) { _tcscpy(&lpszMarker[nResult], _T("/>")); nResult += 2; } else { _tcscpy(&lpszMarker[nResult], _T("/>\n")); nResult += 3; } } else { nResult += nFormat == -1 ? 2 : 3; } } } return nResult;}#undef LENSTR// Create an XML string from the head element.// @param XMLElement * pHead - head element// @param int nFormat - 0 if no formatting is required// otherwise nonzero for formatted text// with carriage returns and indentation.// @param int *pnSize - [out] pointer to the size of the// returned string not including the// NULL terminator.//// @return LPTSTR - Allocated XML string, you must free// this with free().LPTSTR XMLNode::createXMLString(int nFormat, int *pnSize){ if (!d) { if (pnSize) *pnSize=0; return NULL; } LPTSTR lpszResult = NULL; int cbStr; // Recursively Calculate the size of the XML string nFormat = nFormat ? 0 : -1; cbStr = CreateXMLStringR(d, 0, nFormat); assert(cbStr); // Alllocate memory for the XML string + the NULL terminator and // create the recursively XML string. lpszResult=(LPTSTR)malloc((cbStr+1)*sizeof(TCHAR)); CreateXMLStringR(d, lpszResult, nFormat); if (pnSize) *pnSize = cbStr; return lpszResult;}XMLNode::~XMLNode(){ destroyCurrentBuffer(d);};void XMLNode::destroyCurrentBuffer(XMLNodeData *d){ if (!d) return; (d->ref_count) --; if (d->ref_count==0) { int i=0; if (d->pParent) { XMLNode *pa=d->pParent->d->pChild; while (((void*)(pa[i].d))!=((void*)d)) i++; d->pParent->d->nChild--; memmove(pa+i,pa+i+1,(d->pParent->d->nChild-i)*sizeof(XMLNode)); removeOrderElement(d->pParent->d,eNodeChild,i); } for(i=0; i<d->nChild; i++) { d->pChild[i].d->pParent=NULL; destroyCurrentBuffer(d->pChild[i].d); } free(d->pChild); for(i=0; i<d->nText; i++) free((void*)d->pText[i]); free(d->pText); for(i=0; i<d->nClear; i++) free((void*)d->pClear[i].lpszValue); free(d->pClear); for(i=0; i<d->nAttribute; i++) { free((void*)d->pAttribute[i].lpszName); if (d->pAttribute[i].lpszValue) free((void*)d->pAttribute[i].lpszValue); } free(d->pAttribute); free(d->pOrder); free((void*)d->lpszName); free(d); }}XMLNode& XMLNode::operator=( const XMLNode& A ){ // shallow copy if (this != &A) { destroyCurrentBuffer(d); d=A.d; if (d) (d->ref_count) ++ ; } return *this;}XMLNode::XMLNode(const XMLNode &A){ // shallow copy d=A.d; if (d) (d->ref_count)++ ;}int XMLNode::nChildNode(LPCTSTR name){ if (!d) return 0; int i,j=0,n=d->nChild; XMLNode *pc=d->pChild; for (i=0; i<n; i++) { if (_tcsicmp(pc->d->lpszName, name)==0) j++; pc++; } return j;}XMLNode XMLNode::getChildNode(LPCTSTR name, int *j){ if (!d) return emptyXMLNode; int i=0,n=d->nChild; if (j) i=*j; XMLNode *pc=d->pChild+i; for (; i<n; i++) { if (_tcsicmp(pc->d->lpszName, name)==0) { if (j) *j=i+1; return *pc; } pc++; } return emptyXMLNode;}XMLNode XMLNode::getChildNode(LPCTSTR name, int j){ if (!d) return emptyXMLNode; int i=0; while (j-->0) getChildNode(name,&i); return getChildNode(name,&i);}// Find an attribute on an node.LPCTSTR XMLNode::getAttribute(LPCTSTR lpszAttrib, int *j){ if (!d) return NULL; int i=0,n=d->nAttribute; if (j) i=*j; XMLAttribute *pAttr=d->pAttribute+i; for (; i<n; i++) { if (_tcsicmp(pAttr->lpszName, lpszAttrib)==0) { if (j) *j=i+1; return pAttr->lpszValue; } pAttr++; } return NULL;}char XMLNode::isAttributeSet(LPCTSTR lpszAttrib){ if (!d) return FALSE; int i,n=d->nAttribute; XMLAttribute *pAttr=d->pAttribute; for (i=0; i<n; i++) { if (_tcsicmp(pAttr->lpszName, lpszAttrib)==0) { return TRUE; } pAttr++; } return FALSE;}LPCTSTR XMLNode::getAttribute(LPCTSTR name, int j){ if (!d) return NULL; int i=0; while (j-->0) getAttribute(name,&i); return getAttribute(name,&i);}LPCTSTR XMLNode::getName(){ if (!d) return NULL; return d->lpszName; }int XMLNode::nText() { if (!d) return 0; return d->nText; }int XMLNode::nChildNode() { if (!d) return 0; return d->nChild; }int XMLNode::nAttribute() { if (!d) return 0; return d->nAttribute; }int XMLNode::nClear() { if (!d) return 0; return d->nClear; }XMLClear XMLNode::getClear (int i) { if (!d) return emptyXMLClear; if (i>=d->nClear ) return emptyXMLClear; return d->pClear[i]; }XMLAttribute XMLNode::getAttribute (int i) { if (!d) return emptyXMLAttribute; if (i>=d->nAttribute) return emptyXMLAttribute; return d->pAttribute[i]; }LPCTSTR XMLNode::getText (int i) { if (!d) return NULL; if (i>=d->nText ) return NULL; return d->pText[i]; }XMLNode XMLNode::getChildNode (int i) { if (!d) return emptyXMLNode; if (i>=d->nChild ) return emptyXMLNode; return d->pChild[i]; }char XMLNode::isDeclaration( ) { if (!d) return 0; return d->isDeclaration; }char XMLNode::isEmpty ( ) { return (d==NULL); }int XMLNode::nElement ( ) { if (!d) return 0; return d->nChild+d->nText+d->nClear+d->nAttribute; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -