[xsd-users] Getting the tag name in a cxx-parser post_<Type> method

Boris Kolpackov boris at codesynthesis.com
Tue Feb 8 12:22:10 EST 2011


Hi Matthew,

Wood, Matthew D <matthew.d.wood at intel.com> writes:

> At points within the schema where a specific derivative type is reference 
> explicitly, I can infer the tag type based on the element callback of the
> containing parser. In cases where the derivative type is encountered in
> the context of a substitution group, I can differentiate the
> SubjectAttributeDesignatorType due to the extra attributes triggering
> the unique parser, but the other three derivatives only call the parser
> for the common AttributeDesignatorType. When I receive the call to
> post_AttributeDesignatorType (via overridden post_ExpressionType), I
> need to determine the end tag name to properly interpret the semantics
> of the document.

This is the "substitution group element acts as an identifier" pattern
that does not map very cleanly to OO type systems. We had a similar
questions on the XSD/e list some time ago:

http://www.codesynthesis.com/pipermail/xsde-users/2008-October/000072.html

There is unfortunately no elegant way to deal with this in C++/Parser in
XSD (we have added explicit support for the current element querying in
XSD/e thought). The best approach that I can think of right now boils down
to intercepting the SAX callbacks and caching the element name somewhere
where the AttributeDesignatorType can retrieve it.

Here is one way this can be implemented (I assume you are using Xerces-C++
as the underlying XML parser):

1. Create your own SAX2XMLReader parser. See the 'performance' example 
   for the code that shows how to do this.

2. Create your own SAX2 handler by deriving from xercesc::DefaultHandler.
   In the startElement callback save the element name/namespace and call
   the previous handler (can be stored as a member variable). For the
   rest of the callbacks, call the previous handler. For the list of
   callbacks that you need to "forward" see the event_router class in
   libxsd/xsd/cxx/parser/xerces/elements.hxx.

3. Create your own document class that derives from xml_schema::document.
   Add a member variable that stores a reference to SAX2XMLReader and a
   member variable that stores the SAX2 handler created above. Override
   the start_root_element() callback in which you first get the current
   handler and pass it to your customized handler created on step (2)
   (SAX2XMLReader::getDefaultHandler) and then set the custom handler
   as the new current handler (SAX2XMLReader::setDefaultHandler).

   For the code that shows how to override start_root_element(), see the
   'multiroot' example.

4. Pass SAX2 handler to AttributeDesignatorType's c-tor which stores it
   in a member variable for later use. In its pre() callback it can
   then use the handler to retrieve the current element name/namespace.

5. Use the custom document class as the document parser and pass the
   SAX2XMLReader parser to the parse() function.

Boris



More information about the xsd-users mailing list