The following stylesheet creates a simple skeleton that takes a process name and generates stub code:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <!-- Specifies which process to generate handlers for --> <xsl:param name="process"/> <!-- Specifies which message to generate handlers for. A special value of %ALL% signifies all messages --> <xsl:param name="message" select=" '%ALL%' "/> <!-- The directory where --> <xsl:variable name="message-dir" select=" 'messages' "/> <xsl:variable name="directory-sep" select=" '/' "/> <xsl:variable name="include-ext" select=" '.h' "/> <xsl:template match="MessageRepository"> <xsl:choose> <xsl:when test="$message='%ALL%'" > <xsl:apply-templates select="Messages/Message[Receivers/ProcessRef = $process]"/> </xsl:when> <xsl:otherwise> <xsl:apply-templates select="Messages/Message[Receivers/ProcessRef = $process and Name=$message]"/> </xsl:otherwise> </xsl:choose> </xsl:template> <xsl:template match="Message" > <xsl:document href="{concat(Name,'.h')}"> <xsl:call-template name="makeHeader"/> </xsl:document> <xsl:document href="{concat(Name,'.cpp')}"> <xsl:call-template name="makeSource"/> </xsl:document> </xsl:template> <xsl:template name="makeHeader"> #ifndef <xsl:value-of select="Name"/>_h #define <xsl:value-of select="Name"/>_h #include <transport/MessageHandler.h> //Forward Declarations class <xsl:value-of select="DataTypeName"/> ; /*!TODO: Insert addition forward declarations here.*/ class <xsl:value-of select="Name"/> : public MessageHandler { public: <xsl:value-of select="Name"/>(const <xsl:value-of select="DataTypeName"/>& data) ; bool process( ) ; private: const <xsl:value-of select="DataTypeName"/>& m_Data ; } ; #endif </xsl:template> <xsl:template name="makeSource"> #include <messages/<xsl:value-of select="Name"/>.h> /*!TODO: Insert addition includes here.*/ <xsl:value-of select="Name"/>::<xsl:value-of select="Name"/>(const <xsl:value-of select="DataTypeName"/>& data) : m_Data(data) { } bool <xsl:value-of select="Name"/>::process( ) { /*!TODO: Insert message handler code here. */ return true; } </xsl:template> </xsl:stylesheet>
This stylesheet generates a header and a source file for each message it processes, as shown in Example 10-1 and Example 10-2.
Example 10-1. AddStockOrder.h
#ifndef ADD_STOCK_ORDER_h #define ADD_STOCK_ORDER_h #include <transport/MessageHandler.h> //Forward Declarations class AddStockOrderData ; /*!TODO: Insert addition forward declarations here.*/ class ADD_STOCK_ORDER : public MessageHandler { public: ADD_STOCK_ORDER(const AddStockOrderData& data) ; bool process( ) ; private: const AddStockOrderData& m_Data ; } ; #endif
Much of what developers do is repetitive in structure but unique in substance. In other words, we write a lot of boilerplate code that gets specialized based on the particular context. Performing any sort of repetitive work leads to boredom; boredom leads to distraction; and distraction results in bugs. Generating the repetitive parts of your code lets you concentrate on the important parts.
Tools that generate code with
TODO
sections are often called wizards. This
message handler wizard is a very basic example of this genre. Some
commercially available wizards generate the structure of entire
applications. It is not clear whether XSLT can scale to create
wizards of that magnitude. However, for simple kinds of stub
generators for which the input is XML, XSLT is preferable to other
languages, including Perl. Many Perl fanatics disagree with this
statement because they view XML processing as just another form of
text processing (and we all know Perl is the undisputed king of
text-processing languages). However, a strong argument can be made
that XML processing is not text processing, but the processing of
trees that contain text nodes. As such, XSLT facilities transform
trees more nimbly than Perl does. Nevertheless, Perl and XSLT can
team up to create a best-of-both-worlds approach, as shown in Chapter 12. Chapter 12 also presents an
extension to XSLT that removes the verbosity that gets in the way of
pure XSLT-based
generators.