📄 cpl_minixml.cpp
字号:
/* -------------------------------------------------------------------- *//* Anything else is an error. *//* -------------------------------------------------------------------- */ else { CPLError( CE_Failure, CPLE_AppDefined, "Parse error at line %d, unexpected token:%.500s\n", sContext.nInputLine, sContext.pszToken ); break; } }/* -------------------------------------------------------------------- *//* Did we pop all the way out of our stack? *//* -------------------------------------------------------------------- */ if( CPLGetLastErrorType() == CE_None && sContext.nStackSize != 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Parse error at EOF, not all elements have been closed,\n" "starting with %.500s\n", sContext.papsStack[sContext.nStackSize-1]->pszValue ); }/* -------------------------------------------------------------------- *//* Cleanup *//* -------------------------------------------------------------------- */ CPLFree( sContext.pszToken ); if( sContext.papsStack != NULL ) CPLFree( sContext.papsStack ); if( CPLGetLastErrorType() != CE_None ) { CPLDestroyXMLNode( sContext.psFirstNode ); sContext.psFirstNode = NULL; } return sContext.psFirstNode;}/************************************************************************//* _GrowBuffer() *//************************************************************************/static void _GrowBuffer( size_t nNeeded, char **ppszText, unsigned int *pnMaxLength ){ if( nNeeded+1 >= *pnMaxLength ) { *pnMaxLength = MAX(*pnMaxLength * 2,nNeeded+1); *ppszText = (char *) CPLRealloc(*ppszText, *pnMaxLength); }}/************************************************************************//* CPLSerializeXMLNode() *//************************************************************************/static voidCPLSerializeXMLNode( CPLXMLNode *psNode, int nIndent, char **ppszText, unsigned int *pnLength, unsigned int *pnMaxLength ){ if( psNode == NULL ) return; /* -------------------------------------------------------------------- *//* Ensure the buffer is plenty large to hold this additional *//* string. *//* -------------------------------------------------------------------- */ *pnLength += strlen(*ppszText + *pnLength); _GrowBuffer( strlen(psNode->pszValue) + *pnLength + 40 + nIndent, ppszText, pnMaxLength ); /* -------------------------------------------------------------------- *//* Text is just directly emitted. *//* -------------------------------------------------------------------- */ if( psNode->eType == CXT_Text ) { char *pszEscaped = CPLEscapeString( psNode->pszValue, -1, CPLES_XML ); CPLAssert( psNode->psChild == NULL ); /* Escaped text might be bigger than expected. */ _GrowBuffer( strlen(pszEscaped) + *pnLength, ppszText, pnMaxLength ); strcat( *ppszText + *pnLength, pszEscaped ); CPLFree( pszEscaped ); }/* -------------------------------------------------------------------- *//* Attributes require a little formatting. *//* -------------------------------------------------------------------- */ else if( psNode->eType == CXT_Attribute ) { CPLAssert( psNode->psChild != NULL && psNode->psChild->eType == CXT_Text ); sprintf( *ppszText + *pnLength, " %s=\"", psNode->pszValue ); CPLSerializeXMLNode( psNode->psChild, 0, ppszText, pnLength, pnMaxLength ); strcat( *ppszText + *pnLength, "\"" ); }/* -------------------------------------------------------------------- *//* Handle comment output. *//* -------------------------------------------------------------------- */ else if( psNode->eType == CXT_Comment ) { int i; CPLAssert( psNode->psChild == NULL ); for( i = 0; i < nIndent; i++ ) (*ppszText)[(*pnLength)++] = ' '; sprintf( *ppszText + *pnLength, "<!--%s-->\n", psNode->pszValue ); }/* -------------------------------------------------------------------- *//* Handle literal output (like <!DOCTYPE...>) *//* -------------------------------------------------------------------- */ else if( psNode->eType == CXT_Literal ) { int i; CPLAssert( psNode->psChild == NULL ); for( i = 0; i < nIndent; i++ ) (*ppszText)[(*pnLength)++] = ' '; strcpy( *ppszText + *pnLength, psNode->pszValue ); strcat( *ppszText + *pnLength, "\n" ); }/* -------------------------------------------------------------------- *//* Elements actually have to deal with general children, and *//* various formatting issues. *//* -------------------------------------------------------------------- */ else if( psNode->eType == CXT_Element ) { int bHasNonAttributeChildren = FALSE; CPLXMLNode *psChild; memset( *ppszText + *pnLength, ' ', nIndent ); *pnLength += nIndent; (*ppszText)[*pnLength] = '\0'; sprintf( *ppszText + *pnLength, "<%s", psNode->pszValue ); /* Serialize *all* the attribute children, regardless of order */ for( psChild = psNode->psChild; psChild != NULL; psChild = psChild->psNext ) { if( psChild->eType == CXT_Attribute ) CPLSerializeXMLNode( psChild, 0, ppszText, pnLength, pnMaxLength ); else bHasNonAttributeChildren = TRUE; } if( !bHasNonAttributeChildren ) { if( psNode->pszValue[0] == '?' ) strcat( *ppszText + *pnLength, "?>\n" ); else strcat( *ppszText + *pnLength, "/>\n" ); } else { int bJustText = TRUE; strcat( *ppszText + *pnLength, ">" ); for( psChild = psNode->psChild; psChild != NULL; psChild = psChild->psNext ) { if( psChild->eType == CXT_Attribute ) continue; if( psChild->eType != CXT_Text && bJustText ) { bJustText = FALSE; strcat( *ppszText + *pnLength, "\n" ); } CPLSerializeXMLNode( psChild, nIndent + 2, ppszText, pnLength, pnMaxLength ); } *pnLength += strlen(*ppszText + *pnLength); _GrowBuffer( strlen(psNode->pszValue) + *pnLength + 40 + nIndent, ppszText, pnMaxLength ); if( !bJustText ) { memset( *ppszText + *pnLength, ' ', nIndent ); *pnLength += nIndent; (*ppszText)[*pnLength] = '\0'; } *pnLength += strlen(*ppszText + *pnLength); sprintf( *ppszText + *pnLength, "</%s>\n", psNode->pszValue ); } }} /************************************************************************//* CPLSerializeXMLTree() *//************************************************************************//** * \brief Convert tree into string document. * * This function converts a CPLXMLNode tree representation of a document * into a flat string representation. White space indentation is used * visually preserve the tree structure of the document. The returned * document becomes owned by the caller and should be freed with CPLFree() * when no longer needed. * * @param psNode * * @return the document on success or NULL on failure. */char *CPLSerializeXMLTree( CPLXMLNode *psNode ){ unsigned int nMaxLength = 100, nLength = 0; char *pszText = NULL; CPLXMLNode *psThis; pszText = (char *) CPLMalloc(nMaxLength); pszText[0] = '\0'; for( psThis = psNode; psThis != NULL; psThis = psThis->psNext ) CPLSerializeXMLNode( psThis, 0, &pszText, &nLength, &nMaxLength ); return pszText;}/************************************************************************//* CPLCreateXMLNode() *//************************************************************************//** * \brief Create an document tree item. * * Create a single CPLXMLNode object with the desired value and type, and * attach it as a child of the indicated parent. * * @param poParent the parent to which this node should be attached as a * child. May be NULL to keep as free standing. * * @return the newly created node, now owned by the caller (or parent node). */CPLXMLNode *CPLCreateXMLNode( CPLXMLNode *poParent, CPLXMLNodeType eType, const char *pszText ){ CPLXMLNode *psNode;/* -------------------------------------------------------------------- *//* Create new node. *//* -------------------------------------------------------------------- */ psNode = (CPLXMLNode *) CPLCalloc(sizeof(CPLXMLNode),1); psNode->eType = eType; psNode->pszValue = CPLStrdup( pszText );/* -------------------------------------------------------------------- *//* Attach to parent, if provided. *//* -------------------------------------------------------------------- */ if( poParent != NULL ) { if( poParent->psChild == NULL ) poParent->psChild = psNode; else { CPLXMLNode *psLink = poParent->psChild; while( psLink->psNext != NULL ) psLink = psLink->psNext; psLink->psNext = psNode; } } return psNode;}/************************************************************************//* CPLDestroyXMLNode() *//************************************************************************//** * \brief Destroy a tree. * * This function frees resources associated with a CPLXMLNode and all its * children nodes. * * @param psNode the tree to free. */void CPLDestroyXMLNode( CPLXMLNode *psNode ){ if( psNode == NULL ) return; if( psNode->psChild != NULL ) CPLDestroyXMLNode( psNode->psChild ); if( psNode->psNext != NULL ) CPLDestroyXMLNode( psNode->psNext ); CPLFree( psNode->pszValue ); CPLFree( psNode );}/************************************************************************//* CPLSearchXMLNode() *//************************************************************************//** * \brief Search for a node in document. * * Searches the children (and potentially siblings) of the documented * passed in for the named element or attribute. To search following * siblings as well as children, prefix the pszElement name with an equal * sign. This function does an in-order traversal of the document tree. * So it will first match against the current node, then it's first child, * that childs first child, and so on. * * Use CPLGetXMLNode() to find a specific child, or along a specific * node path. * * @param psRoot the subtree to search. This should be a node of type * CXT_Element. NULL is safe. * * @param pszElement the name of the element or attribute to search for. * * @return The matching node or NULL on failure. */CPLXMLNode *CPLSearchXMLNode( CPLXMLNode *psRoot, const char *pszElement ){ int bSideSearch = FALSE; CPLXMLNode *psChild, *psResult; if( psRoot == NULL || pszElement == NULL ) return NULL; if( *pszElement == '=' ) { bSideSearch = TRUE; pszElement++; }/* -------------------------------------------------------------------- *//* Does this node match? *//* -------------------------------------------------------------------- */ if( (psRoot->eType == CXT_Element || psRoot->eType == CXT_Attribute) && EQUAL(pszElement,psRoot->pszValue) ) return psRoot;/* -------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -