 | Level: Introductory Barry Beggs (beggs@us.ibm.com), Pervasive Solution Developer, IBM Joan Boone (jpboone@us.ibm.com), Senior Software Engineer, IBM
01 May 2001 This article describes an atypical use of XSL stylesheets to create applications for pervasive devices by transforming an XML document to source code. The techniques and samples described here were used to implement an application builder tool that generates DB2 Everyplace applications for Palm and EPOC devices.
The big picture
The application builder tool uses XML to define components of the tool user interface and to define the user interface and behavior of the generated application. XML serves this purpose well because it provides an efficient way to structure information about applications that are not highly complex. Pervasive devices usually have a fairly small form factor, which reduces an application's complexity in terms of user interface design and business logic. The XML document produced by the tool is called a project file and is input to the XSLT processor along with several stylesheets. The stylesheets are applied to the project file to generate C source code, and header, resource, and makefiles for a Palm application. The figure below illustrates how the tool uses XML documents and XSL stylesheets.
Using XML and XSL stylesheets
Defining the tool user interface with XML
The application builder for IBM DB2 Everyplace is a drag-and-drop tool that defines its widget set in XML. Defining the widgets in XML enables customization by the application developer and easy extensions when other platforms and user interfaces are added. The tool loads the XML file during initialization and creates the widget palette based on the XML definitions. A PalmOS Button sample is shown in Listing 1.
XML is used to define the name of the button, actions when selected, and properties of the button. The PalmOS PilRC toolset definition is used for the attributes of the widgets, which can be dragged from the palette and dropped on a form as needed.
Defining the generated application user interface and business logic with XML
The application builder also uses XML to store information about the current project. A sample with a database table, one form, and a label on the form is shown in Listing 2.
The project XML document includes definitions for information like the current location, definition of database tables, platform type and details, forms and widgets, and SQL statements. The XSL Stylesheets transform this project XML to a form that can be used to generate target-specific code.
Structuring stylesheets for extensibility
One of the objectives in designing this tool was to enable application generation for multiple target devices in multiple programming languages. For example, the tool generates C applications for Palm and EPOC devices, and is architected to simplify support for other databases or programming languages. The structure of the stylesheets not only lends itself to platform and language extensibility, but also has the added benefit of easing reuse and maintainability of many stylesheets. Here are some of the organizational techniques used:
- XSL for platform-specific code generation is contained in separate stylesheets. For example, individual stylesheets are defined for each Palm user interface resource, such as a form, field, list, or button. Each resource stylesheet contains all of the logic needed to define and manage a resource using the Palm API, such as initializing, setting, and retrieving the contents of a field, or drawing a list.
- XSL for generation of functions that are identical across platforms for a given language are contained in separate stylesheets. For instance, common database functions such as connecting/disconnecting from a database and executing SQL are grouped together in the same stylesheets. Common application functions such as error handling and logging can also be grouped together.
The tool generates code for applications that use a relational database. The XSL for SQL generation is contained in separate stylesheets and can be used across multiple platforms and programming languages. The figure below illustrates the file organization for the stylesheets.
File organization for stylesheets
Generating code
The XSL stylesheets are run against the project XML to create "C" code and supporting files which will be built by the native PalmOS GNU tools. The following XSL sample handles generation of forms (it is extracted from the PersonList sample project that is available with the application builder tool):
<?xml version="1.0" ?>
- <xsl:stylesheet xmlns:xsl="http://www.w3.org/XSL/Transform/1.0">
<xsl:output method="text" />
<xsl:strip-space elements="*" />
<!-- Process all the forms -->
- <xsl:template match="Forms"> #find all forms elements
<xsl:apply-templates select="Form" mode="DrawForm" /> #create code to draw the form
<xsl:apply-templates select="Form" mode="ClearForm" /> #create code to clear form
<xsl:apply-templates select="Form" mode="HandleEvent" />
#here is the main palm event handler
<xsl:text>static Boolean ApplicationHandleEvent(EventPtrevent)
{ FormPtr frm; Int formId; Boolean handled = false;</xsl:text>
- <![CDATA[ #need cdata because of > in code
if (event->eType == frmLoadEvent)
{
formId = event->data.frmLoad.formID;
frm = FrmInitForm(formId);
FrmSetActiveForm(frm);
switch (formId)
{
]]> <xsl:apply-templates select="Form" mode="SetEventHandler"/>
<xsl:text>otherwise: break; } handled = true; } return handled;}</xsl:text>
</xsl:stylesheet>
The following is a section of the "c" code output generated by processing
the project XML in the business logic section of this paper with the above
XSL sample:
/****************************************************************************/
// Draw form
/****************************************************************************/
static void Person_DrawForm()
{
FormPtr form = FrmGetActiveForm();
ListPtr list;
FrmDrawForm(form);
}
static void ClearPerson_()
{
FormPtr form = FrmGetActiveForm();
FrmDrawForm(form);
}
/******************************************************************************/
// Event handlers for each form
/******************************************************************************/
static Boolean Person_HandleEvent(EventPtr event)
{
Boolean handled;
int i;
RectangleType theBounds;
SWord x, y;
Boolean penDown;
RectangleType sigBounds;
handled = false;
switch (event->eType)
{
case ctlSelectEvent:
switch (event->data.ctlEnter.controlID)
{
}
break;
case frmOpenEvent:
SelectFrom_Table1(Table1_RowBuffer.currentSelect,true);
FillIn_Person_Buffer();
Person_DrawForm();
handled = true;
break;
case menuEvent:
switch (event->data.ctlEnter.controlID)
{
}
handled = true;
break;
}
return(handled);
}
static Boolean ApplicationHandleEvent(EventPtr event)
{
FormPtr frm;
Int formId;
Boolean handled = false;
if (event->eType == frmLoadEvent)
{
formId = event->data.frmLoad.formID;
frm = FrmInitForm(formId);
FrmSetActiveForm(frm);
switch (formId)
{
case Person_:
FrmSetEventHandler(frm, Person_HandleEvent);
break;
otherwise:
break;
}
handled = true;
}
return handled;
}
|
Files created in the code generation process are .c, .h., .rcp (GNU resource file), and a makefile. The native Palm application (.prc) is then generated using the Palm GNU toolset.
XSL stylesheet techniques
Using XSL stylesheets to generate code presents some challenges that are not encountered when using stylesheets in a more traditional manner. Transforms from one XML document to another may only require a single pass when the underlying structure of the input and output documents is similar. When generating source code from an XML document, there may be very little similarity between input and output document structures, thus requiring multiple passes though the XML project file to produce the code. For example, when generating code for a form in a Palm application, each Form element must be processed multiple times to produce C code to define data buffers, event handler and initialization functions.
Global variables
Global variables provide an easy way to establish reference points to elements in the project file that are processed multiple times. The variables defined below are used to reference the Project, Tables, and Forms nodes, respectively.
<xsl:variable name="ProjectNode" select="/Project"></xsl:variable>
<xsl:variable name="TablesNode" select="/Project/Tables"></xsl:variable>
<xsl:variable name="FormsNode" select="/Project/Application/Forms"></xsl:variable>
|
The following XSL example illustrates how the Tables node is used. This named template is called with a Table name parameter, which is used to search though each Table node to produce a generic table name, such as Table2, derived from the Table element's position under the Table node.
<xsl:template name="tablePosition">
<xsl:param name="tblprm" >tablename</xsl:param>
<xsl:for-each select="$TablesNode/Table">
<xsl:variable name="tblName"><xsl:value-of select="@name"/></xsl:variable>
<xsl:if test="string($tblName)=string($tblprm)">
<xsl:value-of select="position()"/>
</xsl:if>
</xsl:for-each>
</xsl:template>
|
Reusable templates
The above example also illustrates the use of templates for common, reusable functions. XSLT named templates provide a convenient way to encapsulate common functions that can be called repeatedly. Another example is illustrated below, where a lookup of the SQL data type is performed by passing the corresponding table and column names as parameters. The template generates values like SQL_INTEGER, SQL_CHAR, and SQL_DATE that are used as parameters in SQLBindParameters calls in the generated code. The translated function in this template converts the data type string to uppercase.
<xsl:template name="sqlDatatype">
<xsl:param name="tbl">tableName</xsl:param>
<xsl:param name="col">columnName</xsl:param>
<xsl:variable name="dataType">
<xsl:value-of select="//Table[@name=$tbl]/Column[@name=$col]/@DataType"/>
</xsl:variable>
<xsl:variable name="ucDataType">
<xsl:value-of select='translate($dataType, "Abcdefghijklmnopqrstuvwxyz",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ")'/>
</xsl:variable>
<xsl:text>SQL_</xsl:text>
<xsl:if test="$ucDataType='DATE' or $ucDataType='TIME'">
<xsl:text>TYPE_</xsl:text>
</xsl:if>
<xsl:value-of select="$ucDataType"/>
<xsl:if test="$ucDataType='INT'">
<xsl:text>EGER</xsl:text>
</xsl:if>
</xsl:template>
|
Summary
XSL stylesheets are not generally used to perform transforms where the input and output are as structurally dissimilar as the application project file and C source code. However, we have found them to be very effective for generating pervasive applications that are not as complex as their enterprise counterparts. The user interfaces are simpler as far as number of forms and widget types, and similarly the business logic is not as complex. Hence, the structure of an application is fairly formulaic, a characteristic that lends itself well to a stylesheet implementation.
Resources
About the authors  | |  | Barry Beggs has created palmtop applications as principal partner for GolfTech Products. Barry has also worked on various Telephony and IP projects, most recently working with IP QoS and VoIP H.323 signalling. Current projects are the WebSphere Everyplace Suite SDK, Unified Communication, investigation of databases for WAP clients, and Wireless SIP. Barry can be reached at beggs@us.ibm.com. |
 | |  | Joan Boone is a senior software engineer at IBM Research Triangle Park, NC. She is currently working on enterprise mobility solutions. |
Rate this page
|  |