[xsde-users] Get the currently parsed element's name

Boris Kolpackov boris at codesynthesis.com
Fri Oct 31 04:58:20 EDT 2008


Hi Ninh,

Ninh Tran Dang <tdninh at tma.com.vn> writes:

> We still got segmentation fault with your instruction. In the worst case, we
> will use the "const char* name = _context ().element_name_" in the pre()
> method and then create the object with the stored name variable in the
> post(), we tried and found that it works. But we are not sure if there is
> any further risk because the name variable also points to the element_name
> member of context class which is somehow freed previously.

Ok, I've decided to test the changes I have outlined in my previous
emails on the library example. While setting element_name_ in context
works as expected, there is one thing I stated incorrectly: the parsing
context is not available in the pre() and post_xxx() callbacks. It is
only available between (and including) _pre() and _post(). As you may
remember from the documentation, each parser has four special callbacks:
pre(), _pre(), _post(), and post_xxx(). The callback are called in this
order:

pre()
_pre()
<attribute callbacks>
<nested element callbacks>
_post()
post_xxx()

The call to _context() is only valid starting from _pre() and
ending with _post(). If you are creating the object in post_xxx(),
one way to change your code would be as follows:

struct inner_pimpl: inner_pskel
{
  virtual void
  _post ()
  {
    const char* name = _context ().element_name_;
    ret_ = new inner_t (name);
  }

  virtual inner_t*
  post_inner ()
  {  
    return ret_;
  }  

private:
  inner_t* ret_;
};

Alternatively, you can save a copy of the name in _pre() or _post() 
and then use that copy in post_xxx():

struct inner_pimpl: inner_pskel
{
  virtual void
  _post ()
  {
    element_name_ = strdup (_context ().element_name_);
  }

  virtual inner_t*
  post_inner ()
  {  
    return new inner_t (element_name_); // Assumes ownership of element_name_.
  }  

private:
  char* element_name_;
};

If you are already using pre() and would like to keep the number of
callbacks to a minimum then you can just replace pre() with _pre()
and save the element name there. The only requirement is that in
_pre() you always need to call the version from the base parser
if there is one. For more information on the difference between
pre() and _pre(), see Section 3.1 in Chapter 3, "Parser Skeletons"
in the Embedded C++/Parser Mapping Getting Started Guide:

http://www.codesynthesis.com/projects/xsde/documentation/cxx/parser/guide/#3.1

Boris



More information about the xsde-users mailing list