I written a wrapper around  xmlXPathNewContext and  xmlXPathEvalExpression
(maybe re-inventing the wheel :) ) to obtain an xmlXPathObjectPtr.
Here below there is the function:
/**
 *
=====================================================================================
 *@fn xmlXPathObjectPtr get_xml_elements(xmlNodePtr nodePtr,char
*elementName)
 *         @brief this function looks for elements named elementName in the
 *         passed xmlNodePtr.
 *         @param nodePtr a  xmlNodePtr where to look for element named
 *         elementName
 *         @param context an xmlXPathContextPtr passed in case of recursive
 *         parsing and recusive use of get_xml_elements
 *         @return xmlXPathObjectPtr containing one or more element named
 *         elementName. NOTE: Returned pointer must be freed by the caller
with
 *         xmlXPathFreeObject()
 *
=====================================================================================
 */
xmlXPathObjectPtr get_xml_elements(xmlNodePtr nodePtr,char *elementName)
{
  xmlXPathObjectPtr result=NULL;
  xmlChar * lookup=NULL;
  int extraSpace=strlen("child::");
  xmlXPathContextPtr context=NULL;
  /** check parameters */
  if(nodePtr==NULL || elementName == NULL){
    ERRORS(EINVAL,"null pointer param
passed\nnodePtr=%p,elementName=%p",nodePtr,elementName);
    return NULL;
  }

  /** xmlXPathNewContext allocs a xmlXPathContextPtr */

  context = xmlXPathNewContext(nodePtr->doc);
  if(context==NULL){
    ERRORS(ENOMEM,"xmlXPathNewContext fails\n");
    return NULL;
  }
  /** configure node, the current node, to the one passed in the arg */
  context->node=nodePtr;

  /** resize lookup of extraspace+1 :1 for \0 and extraspace for axis */
  lookup=calloc(strlen(elementName)+extraSpace+1,sizeof(xmlChar));
  if(lookup==NULL){
    ERRORS(ENOMEM,"Error allocating space for alloc new string
child::%s\n",elementName);
    return NULL;
  }
  strcat((char *)lookup,"child::");
  strcat((char *)lookup,elementName);
  result = xmlXPathEvalExpression(lookup,context);
  free(lookup);

  xmlXPathFreeContext(context);
  if(result == NULL){
    ERROR("error in xmlXPathEvalExpression\n");
    return NULL;
  }
  if(xmlXPathNodeSetIsEmpty(result->nodesetval)){
    xmlXPathFreeObject(result);
    ERROR("No Element %s found\n",elementName);
    //print_element_names((xmlNodePtr)nodePtr);
    return NULL;
  }
  return result;
}

the returned xmlXPathObjectPtr is used to cycle on the single element and
it's possible that during that, get_xml_elements is called again passing as
nodePtr parameter the node obtained from the previous call to
xml_get_elements.
It happens that on the second call I get a segmentation fault creating the
context:
context = xmlXPathNewContext(nodePtr->doc);
here the stack:

malloc () from /lib/libc.so.6
xmlHashCreate () from /usr/lib/libxml2.so.2
xmlXPathNewContext () from /usr/lib/libxml2.so.2
get_xml_elements (nodePtr=0x8057940, elementName=0x804e51d "field",
context=0x0) at xmlParse.c:169

Can someone tell me if I'm doing a well known error, that is: creating a
context by using an element obtained from a previous created and already
freed context?
I hope the question is clear.
 Regards
   zad
_______________________________________________
xml mailing list, project page  http://xmlsoft.org/
[email protected]
http://mail.gnome.org/mailman/listinfo/xml

Reply via email to