Search code examples
xmlxpathlibxml2

Libxml2 usage -- total novice


I am new to using the libxml2, in fact this will be my very first time. I've been looking to find some sample code that could point me in the correct direction but so far I've been absolutely unsuccessful. I am attempting to use the following XPath statement:

"$XTX//DeptName[ . = $Dn ]"

However, I cannot figure out how to produce and evaluate a query with variables ($XTX and $Dn). I cannot figure out how to add the variable substitution to the code. I assume I will need the xmlXPathRegisterVariable API but as I said I simply cannot figure out how to do that. Can anyone either provide me or point me to some sample code that I can use to get this working?

        if ( 0 != iXmlArrDim ) { 
        Assert( XMLOID == ARR_ELEMENTS( pXmlDataArr ) );

        deconstruct_array( pXmlDataArr,
                           XMLOID,
                           -1, 
                           false,
                           'i',
                           &pXmlData,
                           &pXmlDataNulls,
                           (int32_t*)&iXmlCount );

        /** 
         */
        xmltype  *pX    = NULL;
        char     *pData = "<\\>";
        uint32_t  iData = sizeof( "<\\>" ) - 1;

        if ( !pXmlDataNulls[0] ) { 
            pX    = DatumGetXmlP( pXmlData[0] );
            pData = VARDATA( pX );
            iData = VARSIZE( pX ) - VARHDRSZ;

            pDoc = xmlCtxtReadMemory( pCtx, pData, iData, NULL, NULL, 0 );

            if ( NULL == pDoc )
                ereport( ERROR,
                         ( errcode( ERRCODE_INVALID_XML_DOCUMENT ),
                           errmsg( "Could not parse the XML document" ) ) );

            pXPathCtx = xmlXPathNewContext( pDoc );

            if ( NULL == pXPathCtx )
                ereport( ERROR,
                         ( errcode( ERRCODE_OUT_OF_MEMORY ),
                           errmsg( "Could not allocate XPath context" ) ) );

            pXPathCtx->node = (xmlNodePtr)pDoc;

            pXPathObj = xmlXPathEval( pXPathStr, pXPathCtx );
            //pXPathObj = xmlXPathEvalExpression( pXPathStr, pXPathCtx );

            /** 
             * Add any additional XML items or variables.
             */
            for ( size_t ix = 1; ix < ( iXmlCount >> 1 ); ++ix ) { 
                int                rc        = 0;
                xmlXPathObjectPtr  pXPathObj = NULL;
                const char        *pAlias    = NULL;

                pX    = DatumGetXmlP( pXmlData[ix * 2] );
                pData = VARDATA( pX );
                iData = VARSIZE( pX ) - VARHDRSZ;

                /** 
                 * Add the alias as a variable if one was specified.
                 */
                if ( !pXmlDataNulls[( ix * 2 ) + 1] ) { 
                    pAlias = TextDatumGetCString( pXmlData[ix * 2] );

                    rc = xmlXPathRegisterVariable( pXPathCtx,
                                                   BAD_CAST pAlias,
                                                   xmlXPathObjectCopy( pXPathObj ) );

                    if ( rc == -1 )
                        ereport( WARNING,
                                 ( errcode( ERRCODE_INTERNAL_ERROR ),
                                 errmsg( "Could not create an XPath object" ) ) );
                }   
            }   
        }   
    }

Regards, Garfield


Solution

  • ok, so after a lot of debugging I've figured it out. Basically, the following change to my code now allows me to set the variable as expected:

                        pAlias = TextDatumGetCString( pXmlData[( ix * 2 ) + 1] );
                        pValue = xmlXPathNewString( BAD_CAST pData );
                        rc     = xmlXPathRegisterVariable( pXPathCtx,
                                                           BAD_CAST pAlias,
                                                           pValue );
    
                        if ( rc == -1 )
                            ereport( WARNING,
                                     ( errcode( ERRCODE_INTERNAL_ERROR ),
                                       errmsg( "Could not create an XPath object" ) ) );
    

    Subsequent to this, the xmlXPathEval is moved below the for loop to register the variables.