⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpl_minixml.cpp

📁 mitab,读取MapInfo的地图文件
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    CPLXMLNode *psReturn = NULL;

    while( psTree != NULL )
    {
        CPLXMLNode *psCopy;

        psCopy = CPLCreateXMLNode( NULL, psTree->eType, psTree->pszValue );
        if( psReturn == NULL )
            psReturn = psCopy;
        if( psPrevious != NULL )
            psPrevious->psNext = psCopy;

        if( psTree->psChild != NULL )
            psCopy->psChild = CPLCloneXMLTree( psTree->psChild );

        psPrevious = psCopy;
        psTree = psTree->psNext;
    }

    return psReturn;
}

/************************************************************************/
/*                           CPLSetXMLValue()                           */
/************************************************************************/

/**
 * \brief Set element value by path. 
 *
 * Find (or create) the target element or attribute specified in the
 * path, and assign it the indicated value. 
 *
 * Any path elements that do not already exist will be created.  The target
 * nodes value (the first CXT_Text child) will be replaced with the provided
 * value.  
 *
 * If the target node is an attribute instead of an element, the last separator
 * should be a "#" instead of the normal period path separator. 
 *
 * Example:
 *   CPLSetXMLValue( "Citation.Id.Description", "DOQ dataset" );
 *   CPLSetXMLValue( "Citation.Id.Description#name", "doq" );
 *
 * @param psRoot the subdocument to be updated. 
 *
 * @param pszPath the dot seperated path to the target element/attribute.
 *
 * @param pszValue the text value to assign. 
 *
 * @return TRUE on success.
 */

int CPLSetXMLValue( CPLXMLNode *psRoot,  const char *pszPath,
                    const char *pszValue )

{
    char        **papszTokens;
    int         iToken = 0;

    papszTokens = CSLTokenizeStringComplex( pszPath, ".", FALSE, FALSE );

    while( papszTokens[iToken] != NULL && psRoot != NULL )
    {
        CPLXMLNode *psChild;
        int        bIsAttribute = FALSE;
        const char *pszName = papszTokens[iToken];

        if( pszName[0] == '#' )
        {
            bIsAttribute = TRUE;
            pszName++;
        }

        if( psRoot->eType != CXT_Element )
            return FALSE;

        for( psChild = psRoot->psChild; psChild != NULL; 
             psChild = psChild->psNext ) 
        {
            if( psChild->eType != CXT_Text 
                && EQUAL(pszName,psChild->pszValue) )
                break;
        }

        if( psChild == NULL )
        {
            if( bIsAttribute )
                psChild = CPLCreateXMLNode( psRoot, CXT_Attribute, pszName );
            else
                psChild = CPLCreateXMLNode( psRoot, CXT_Element, pszName );
        }

        psRoot = psChild;
        iToken++;
    }

    CSLDestroy( papszTokens );

/* -------------------------------------------------------------------- */
/*      Find the "text" child if there is one.                          */
/* -------------------------------------------------------------------- */
    CPLXMLNode *psTextChild = psRoot->psChild;

    while( psTextChild != NULL && psTextChild->eType != CXT_Text )
        psTextChild = psTextChild->psNext;

/* -------------------------------------------------------------------- */
/*      Now set a value node under this node.                           */
/* -------------------------------------------------------------------- */
    
    if( psTextChild == NULL )
        CPLCreateXMLNode( psRoot, CXT_Text, pszValue );
    else 
    {
        CPLFree( psTextChild->pszValue );
        psTextChild->pszValue = CPLStrdup( pszValue );
    }

    return TRUE;
}

/************************************************************************/
/*                        CPLStripXMLNamespace()                        */
/************************************************************************/

/**
 * \brief Strip indicated namespaces. 
 *
 * The subdocument (psRoot) is recursively examined, and any elements
 * with the indicated namespace prefix will have the namespace prefix
 * stripped from the element names.  If the passed namespace is NULL, then
 * all namespace prefixes will be stripped. 
 *
 * Nodes other than elements should remain unaffected.  The changes are
 * made "in place", and should not alter any node locations, only the 
 * pszValue field of affected nodes. 
 *
 * @param psRoot the document to operate on.
 * @param pszNamespace the name space prefix (not including colon), or NULL.
 * @param bRecurse TRUE to recurse over whole document, or FALSE to only
 * operate on the passed node.
 */

void CPLStripXMLNamespace( CPLXMLNode *psRoot, 
                           const char *pszNamespace, 
                           int bRecurse )

{
    if( psRoot == NULL )
        return;

    if( psRoot->eType == CXT_Element || psRoot->eType == CXT_Attribute )
    {
        if( pszNamespace != NULL )
        {
            if( EQUALN(pszNamespace,psRoot->pszValue,strlen(pszNamespace)) 
                && psRoot->pszValue[strlen(pszNamespace)] == ':' )
            {
                char *pszNewValue = 
                    CPLStrdup(psRoot->pszValue+strlen(pszNamespace)+1);
                
                CPLFree( psRoot->pszValue );
                psRoot->pszValue = pszNewValue;
            }
        }
        else
        {
            const char *pszCheck;
            
            for( pszCheck = psRoot->pszValue; *pszCheck != '\0'; pszCheck++ )
            {
                if( *pszCheck == ':' )
                {
                    char *pszNewValue = CPLStrdup( pszCheck+1 );
                    
                    CPLFree( psRoot->pszValue );
                    psRoot->pszValue = pszNewValue;
                    break;
                }
            }
        }
    }

    if( bRecurse )
    {
        if( psRoot->psChild != NULL )
            CPLStripXMLNamespace( psRoot->psChild, pszNamespace, 1 );
        if( psRoot->psNext != NULL )
            CPLStripXMLNamespace( psRoot->psNext, pszNamespace, 1 );
    }
}

/************************************************************************/
/*                          CPLParseXMLFile()                           */
/************************************************************************/

/**
 * \brief Parse XML file into tree.
 *
 * The named file is opened, loaded into memory as a big string, and
 * parsed with CPLParseXMLString().  Errors in reading the file or parsing
 * the XML will be reported by CPLError(). 
 *
 * The "large file" API is used, so XML files can come from virtualized
 * files. 
 *
 * @param pszFilename the file to open. 
 *
 * @return NULL on failure, or the document tree on success.
 */

CPLXMLNode *CPLParseXMLFile( const char *pszFilename )

{
    FILE            *fp;
    vsi_l_offset    nLen;
    char            *pszDoc;
    CPLXMLNode      *psTree;

/* -------------------------------------------------------------------- */
/*      Read the file.                                                  */
/* -------------------------------------------------------------------- */
    fp = VSIFOpenL( pszFilename, "rb" );
    if( fp == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "Failed to open %.500s to read.", pszFilename );
        return NULL;
    }

    VSIFSeekL( fp, 0, SEEK_END );
    nLen = VSIFTellL( fp );
    VSIFSeekL( fp, 0, SEEK_SET );
    
    pszDoc = (char *) VSIMalloc((size_t)nLen + 1);
    if( pszDoc == NULL )
    {
        CPLError( CE_Failure, CPLE_OutOfMemory, 
                  "Out of memory allocating space for %d byte buffer in\n"
                  "CPLParseXMLFile(%.500s).", 
                  nLen+1, pszFilename );
        VSIFCloseL( fp );
        return NULL;
    }
    if( VSIFReadL( pszDoc, 1, (size_t)nLen, fp ) < nLen )
    {
        CPLError( CE_Failure, CPLE_FileIO, 
                  "VSIFRead() result short of expected %d bytes from %.500s.", 
                  nLen, pszFilename );
        pszDoc[0] = '\0';
    }
    VSIFCloseL( fp );

    pszDoc[nLen] = '\0';

/* -------------------------------------------------------------------- */
/*      Parse it.                                                       */
/* -------------------------------------------------------------------- */
    psTree = CPLParseXMLString( pszDoc );
    CPLFree( pszDoc );

    return psTree;
}

/************************************************************************/
/*                     CPLSerializeXMLTreeToFile()                      */
/************************************************************************/

/**
 * \brief Write document tree to a file. 
 *
 * The passed document tree is converted into one big string (with 
 * CPLSerializeXMLTree()) and then written to the named file.  Errors writing
 * the file will be reported by CPLError().  The source document tree is
 * not altered.  If the output file already exists it will be overwritten. 
 *
 * @param psTree the document tree to write. 
 * @param pszFilename the name of the file to write to. 
 * @return TRUE on success, FALSE otherwise.
 */

int CPLSerializeXMLTreeToFile( CPLXMLNode *psTree, const char *pszFilename )

{
    char    *pszDoc;
    FILE    *fp;
    vsi_l_offset nLength;

/* -------------------------------------------------------------------- */
/*      Serialize document.                                             */
/* -------------------------------------------------------------------- */
    pszDoc = CPLSerializeXMLTree( psTree );
    if( pszDoc == NULL )
        return FALSE;

    nLength = strlen(pszDoc);

/* -------------------------------------------------------------------- */
/*      Create file.                                                    */
/* -------------------------------------------------------------------- */
    fp = VSIFOpenL( pszFilename, "wt" );
    if( fp == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "Failed to open %.500s to write.", pszFilename );
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Write file.                                                     */
/* -------------------------------------------------------------------- */
    if( VSIFWriteL( pszDoc, 1, nLength, fp ) != nLength )
    {
        CPLError( CE_Failure, CPLE_FileIO, 
                  "Failed to write whole XML document (%.500s).",
                  pszFilename );
        VSIFCloseL( fp );
        CPLFree( pszDoc );
        return FALSE;
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
    VSIFCloseL( fp );
    CPLFree( pszDoc );

    return TRUE;
}

/************************************************************************/
/*                       CPLCleanXMLElementName()                       */
/************************************************************************/

/**
 * \brief Make string into safe XML token.
 *
 * Modififies a string in place to try and make it into a legal
 * XML token that can be used as an element name.   This is accomplished
 * by changing any characters not legal in a token into an underscore. 
 * 
 * NOTE: This function should implement the rules in section 2.3 of 
 * http://www.w3.org/TR/xml11/ but it doesn't yet do that properly.  We
 * only do a rough approximation of that.
 *
 * @param pszTarget the string to be adjusted.  It is altered in place. 
 */

void CPLCleanXMLElementName( char *pszTarget )
{
    if( pszTarget == NULL )
        return;

    for( ; *pszTarget != '\0'; pszTarget++ )
    {
        if( (*((unsigned char *) pszTarget) & 0x80) || isalnum( *pszTarget )
            || *pszTarget == '_' || *pszTarget == '.' )
        {
            /* ok */
        }
        else
        {
            *pszTarget = '_';
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -