📄 cpl_minixml.cpp
字号:
/* Search children. *//* -------------------------------------------------------------------- */ for( psChild = psRoot->psChild; psChild != NULL; psChild = psChild->psNext) { if( (psChild->eType == CXT_Element || psChild->eType == CXT_Attribute) && EQUAL(pszElement,psChild->pszValue) ) return psChild; if( psChild->psChild != NULL ) { psResult = CPLSearchXMLNode( psChild, pszElement ); if( psResult != NULL ) return psResult; } }/* -------------------------------------------------------------------- *//* Search siblings if we are in side search mode. *//* -------------------------------------------------------------------- */ if( bSideSearch ) { for( psRoot = psRoot->psNext; psRoot != NULL; psRoot = psRoot->psNext ) { psResult = CPLSearchXMLNode( psRoot, pszElement ); if( psResult != NULL ) return psResult; } } return NULL;}/************************************************************************//* CPLGetXMLNode() *//************************************************************************//** * \brief Find node by path. * * Searches the document or subdocument indicated by psRoot for an element * (or attribute) with the given path. The path should consist of a set of * element names separated by dots, not including the name of the root * element (psRoot). If the requested element is not found NULL is returned. * * Attribute names may only appear as the last item in the path. * * The search is done from the root nodes children, but all intermediate * nodes in the path must be specified. Seaching for "name" would only find * a name element or attribute if it is a direct child of the root, not at any * level in the subdocument. * * If the pszPath is prefixed by "=" then the search will begin with the * root node, and it's siblings, instead of the root nodes children. This * is particularly useful when searching within a whole document which is * often prefixed by one or more "junk" nodes like the <?xml> declaration. * * @param psRoot the subtree in which to search. This should be a node of * type CXT_Element. NULL is safe. * * @param pszPath the list of element names in the path (dot separated). * * @return the requested element node, or NULL if not found. */CPLXMLNode *CPLGetXMLNode( CPLXMLNode *psRoot, const char *pszPath ){ char **papszTokens; int iToken = 0; int bSideSearch = FALSE; if( psRoot == NULL ) return NULL; if( *pszPath == '=' ) { bSideSearch = TRUE; pszPath++; } papszTokens = CSLTokenizeStringComplex( pszPath, ".", FALSE, FALSE ); while( papszTokens[iToken] != NULL && psRoot != NULL ) { CPLXMLNode *psChild; if( bSideSearch ) { psChild = psRoot; bSideSearch = FALSE; } else psChild = psRoot->psChild; for( ; psChild != NULL; psChild = psChild->psNext ) { if( psChild->eType != CXT_Text && EQUAL(papszTokens[iToken],psChild->pszValue) ) break; } if( psChild == NULL ) { psRoot = NULL; break; } psRoot = psChild; iToken++; } CSLDestroy( papszTokens ); return psRoot;}/************************************************************************//* CPLGetXMLValue() *//************************************************************************//** * \brief Fetch element/attribute value. * * Searches the document for the element/attribute value associated with * the path. The corresponding node is internally found with CPLGetXMLNode() * (see there for details on path handling). Once found, the value is * considered to be the first CXT_Text child of the node. * * If the attribute/element search fails, or if the found node has not * value then the passed default value is returned. * * The returned value points to memory within the document tree, and should * not be altered or freed. * * @param psRoot the subtree in which to search. This should be a node of * type CXT_Element. NULL is safe. * * @param pszPath the list of element names in the path (dot separated). An * empty path means get the value of the psRoot node. * * @param pszDefault the value to return if a corresponding value is not * found, may be NULL. * * @return the requested value or pszDefault if not found. */const char *CPLGetXMLValue( CPLXMLNode *psRoot, const char *pszPath, const char *pszDefault ){ CPLXMLNode *psTarget; if( pszPath == NULL || *pszPath == '\0' ) psTarget = psRoot; else psTarget = CPLGetXMLNode( psRoot, pszPath ); if( psTarget == NULL ) return pszDefault; if( psTarget->eType == CXT_Attribute ) { CPLAssert( psTarget->psChild != NULL && psTarget->psChild->eType == CXT_Text ); return psTarget->psChild->pszValue; } if( psTarget->eType == CXT_Element ) { // Find first non-attribute child, and verify it is a single text // with no siblings psTarget = psTarget->psChild; while( psTarget != NULL && psTarget->eType == CXT_Attribute ) psTarget = psTarget->psNext; if( psTarget != NULL && psTarget->eType == CXT_Text && psTarget->psNext == NULL ) return psTarget->pszValue; } return pszDefault;}/************************************************************************//* CPLAddXMLChild() *//************************************************************************//** * \brief Add child node to parent. * * The passed child is added to the list of children of the indicated * parent. Normally the child is added at the end of the parents child * list, but attributes (CXT_Attribute) will be inserted after any other * attributes but before any other element type. Ownership of the child * node is effectively assumed by the parent node. If the child has * siblings (it's psNext is not NULL) they will be trimmed, but if the child * has children they are carried with it. * * @param psParent the node to attach the child to. May not be NULL. * * @param psChild the child to add to the parent. May not be NULL. Should * not be a child of any other parent. */void CPLAddXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild ){ CPLXMLNode *psSib; if( psParent->psChild == NULL ) { psParent->psChild = psChild; return; } // Insert at head of list if first child is not attribute. if( psChild->eType == CXT_Attribute && psParent->psChild->eType != CXT_Attribute ) { psChild->psNext = psParent->psChild; psParent->psChild = psChild; return; } // Search for end of list. for( psSib = psParent->psChild; psSib->psNext != NULL; psSib = psSib->psNext ) { // Insert attributes if the next node is not an attribute. if( psChild->eType == CXT_Attribute && psSib->psNext != NULL && psSib->psNext->eType != CXT_Attribute ) { psChild->psNext = psSib->psNext; psSib->psNext = psChild; return; } } psSib->psNext = psChild;}/************************************************************************//* CPLAddXMLChild() *//************************************************************************//** * \brief Remove child node from parent. * * The passed child is removed from the child list of the passed parent, * but the child is not destroyed. The child retains ownership of it's * own children, but is cleanly removed from the child list of the parent. * * @param psParent the node to the child is attached to. * * @param psChild the child to remove. * * @return TRUE on success or FALSE if the child was not found. */int CPLRemoveXMLChild( CPLXMLNode *psParent, CPLXMLNode *psChild ){ CPLXMLNode *psLast = NULL, *psThis; if( psParent == NULL ) return FALSE; for( psThis = psParent->psChild; psThis != NULL; psThis = psThis->psNext ) { if( psThis == psChild ) { if( psLast == NULL ) psParent->psChild = psThis->psNext; else psLast->psNext = psThis->psNext; psThis->psNext = NULL; return TRUE; } } return FALSE;}/************************************************************************//* CPLAddXMLSibling() *//************************************************************************//** * \brief Add new sibling. * * The passed psNewSibling is added to the end of siblings of the * psOlderSibling node. That is, it is added to the end of the psNext * chain. There is no special handling if psNewSibling is an attribute. * If this is required, use CPLAddXMLChild(). * * @param psOlderSibling the node to attach the sibling after. * * @param psNewSibling the node to add at the end of psOlderSiblings psNext * chain. */void CPLAddXMLSibling( CPLXMLNode *psOlderSibling, CPLXMLNode *psNewSibling ){ if( psOlderSibling == NULL ) return; while( psOlderSibling->psNext != NULL ) psOlderSibling = psOlderSibling->psNext; psOlderSibling->psNext = psNewSibling;}/************************************************************************//* CPLCreateXMLElementAndValue() *//************************************************************************//** * \brief Create an element and text value. * * This is function is a convenient short form for: * * \code * CPLXMLNode *psTextNode; * CPLXMLNode *psElementNode; * * psElementNode = CPLCreateXMLNode( psParent, CXT_Element, pszName ); * psTextNode = CPLCreateXMLNode( psElementNode, CXT_Text, pszValue ); * * return psElementNode; * \endcode * * It creates a CXT_Element node, with a CXT_Text child, and * attaches the element to the passed parent. * * @param psParent the parent node to which the resulting node should * be attached. May be NULL to keep as freestanding. * * @param pszName the element name to create. * @param pszValue the text to attach to the element. Must not be NULL. * * @return the pointer to the new element node. */CPLXMLNode *CPLCreateXMLElementAndValue( CPLXMLNode *psParent, const char *pszName, const char *pszValue ){ CPLXMLNode *psTextNode; CPLXMLNode *psElementNode; psElementNode = CPLCreateXMLNode( psParent, CXT_Element, pszName ); psTextNode = CPLCreateXMLNode( psElementNode, CXT_Text, pszValue ); return psElementNode;}/************************************************************************//* CPLCloneXMLTree() *//************************************************************************//** * \brief Copy tree. * * Creates a deep copy of a CPLXMLNode tree. * * @param psTree the tree to duplicate.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -