|
||||
SummaryIn part 2 we built an XRL template and showed how active content can be included. We also created an XForm to enter new data. We now need to complete the XForm data submission and finish the browser. XForm submissionPreviously we said that once an XForm's constraints are satisfied a the submission target, in this app xform_process.idoc will be called with the instance data supplied as parameter. Here is an idoc to create a database entry from the instance data... <idoc>
<seq> <instr> <type>stm</type> <operand> <sql /> </operand> <operator> <stm:group xmlns:stm="http://1060.org/stm"> <stm:set xpath="/sql"> INSERT INTO entries VALUES ( null, ' <stm:param xpath="/nvp/firstname/text()" />', ' <stm:param xpath="/nvp/lastname/text()" />', ' <stm:param xpath="/nvp/add1/text()" />', ' <stm:param xpath="/nvp/add2/text()" />', ' <stm:param xpath="/nvp/add3/text()" />', ' <stm:param xpath="/nvp/add4/text()" />', ' <stm:param xpath="/nvp/region/text()" />', ' <stm:param xpath="/nvp/country/text()" />', ' <stm:param xpath="/nvp/zip/text()" />', ' <stm:param xpath="/nvp/phone1/text()" />', ' <stm:param xpath="/nvp/phone2/text()" />', ' <stm:param xpath="/nvp/phone3/text()" />', ' <stm:param xpath="/nvp/fax/text()" />', ' <stm:param xpath="/nvp/email1/text()" />', ' <stm:param xpath="/nvp/email2/text()" />', ' <stm:param xpath="/nvp/email3/text()" />', ' <stm:param xpath="/nvp/web1/text()" />', ' <stm:param xpath="/nvp/web2/text()" />', ' <stm:param xpath="/nvp/notes/text()" />' ); </stm:set> </stm:group> </operator> <param>this:param</param> <target>var:sql</target> </instr> <instr> <type>sqlUpdate</type> <operand>var:sql</operand> <target>this:response</target> </instr> <instr> <type>buildSessionResourceURI</type> <operand>this:param:session</operand> <operator> <key>xform</key> </operator> <target>var:xformSession</target> </instr> <instr> <type>delete</type> <operand>curi:var:xformSession</operand> </instr> <instr> <type>HTTPredirect</type> <operand> <uri>/addressbook/</uri> </operand> <target>this:response</target> </instr> </seq> </idoc> This process dynamically builds an SQL INSERT statement from the submitted parameter. It uses the sqlUpdate accessor to execute the SQL statement on the RDBMS. The new entry is then in the DB. Finally it deletes the XForm from the session - it is not important here how this is done other than to say all session resources are referenced by URI and that the key for an XForm session object is 'xform'. The result is the XForm is finished with and the entry is in the database. Finally we do an HTTPredirect back to the main page. Main BrowserWe've got a means of entering data we now need to enable the record browser. First we need to make the "main" link active and create a source of content. Edit the main link as shown below and add the new "browser" link which executes browser.idoc. <links>
...
<link> <name>main</name> <ext>/</ext> <int>active:xrl-html+operator@ffcpl:/links.xml+template@ffcpl:/resources/mastertemplate.xml+content@xrl:browser</int> <args>links,param,session</args> </link> <link> <name>browser</name> <int>active:dpml+operand@ffcpl:/resources/browser.idoc</int> <args>links,param,session</args> </link> </links> The changes to the links now mean that the main page will pull in the content supplied from the browser.idoc. Here is the browser.idoc, copy this to resources/ <idoc>
<seq> <instr> <type>stm</type> <operand> <sql /> </operand> <operator> <stm:group xmlns:stm="http://1060.org/stm"> <stm:set xpath="/sql"> SELECT * FROM entries WHERE lastname LIKE ' <stm:param xpath="/nvp/letter/text()" />%' OR lastname LIKE ' <stm:param xpath="translate(/nvp/letter/text(), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" />%' ORDER BY lastname; </stm:set> </stm:group> </operator> <param>this:param</param> <target>var:sql</target> </instr> <instr> <type>sqlQuery</type> <operand>var:sql</operand> <target>this:response</target> </instr> <instr> <type>xslt</type> <operand>this:response</operand> <operator>style_address.xsl</operator> <param>this:param</param> <target>this:response</target> </instr> <exception> <instr> <type>copy</type> <operand> <div /> </operand> <target>this:response</target> </instr> </exception> </seq> </idoc>
This process dynamically generates an SQL query statement using the
But what is the parameter? Remember
that we said the REST interface to the main page is So we have a dynamically created SQL query - it matches surnames begining with a given letter (we use an XPath trick to support upper case as well as lower case). Next the SQL query is made on the DB using the sqlQuery accessor. Finally the results of the query are styled with a stylesheet (provided below, copy this as 'style_address.xsl' to resources/). That's it you can now click on a letter and view all the matching entries. We'll leave it as an exercise to add the search facillity, there are many other ways this app can be improved, like supporting editing and deletion of entries etc. If you want to cheat you can download and install the complete application using the install wizard - this includes the search and has a glamorous CSS stylesheet too! <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" /> <xsl:param name="param" /> <xsl:template match="/"> <div> <xsl:choose> <xsl:when test="$param/nvp/letter"> <div style="font-size: 30px;"> <xsl:value-of select="translate($param/nvp/letter, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')" /> </div> </xsl:when> <xsl:otherwise> <div style="font-size: 30px;"> <xsl:value-of select="$param/nvp/search" /> </div> </xsl:otherwise> </xsl:choose> <xsl:apply-templates /> </div> </xsl:template> <xsl:template match="null"> <div style="font-size: 15px; margin-left: 5px; margin-top: 5px;">No Entries</div> </xsl:template> <xsl:template match="results"> <xsl:apply-templates /> </xsl:template> <xsl:template match="row"> <table cellpadding="0" cellspacing="0" style="margin-top: 15px; margin-bottom: 15px;"> <tr> <td> <table cellpadding="0" cellspacing="0" style="padding: 5px; margin-bottom:5px;"> <tr> <td colspan="10"> <table cellpadding="0" cellspacing="0" style="padding-right: 5px"> <tr> <td style="padding-right: 5px;"> <xsl:value-of select="lastname" /> </td> <td> <xsl:value-of select="firstname" /> </td> </tr> </table> </td> </tr> <tr> <td valign="top" width="200"> <table cellpadding="0" cellspacing="0" style="padding-right: 5px"> <tr> <td> <xsl:value-of select="add1" /> </td> </tr> <tr> <td> <xsl:value-of select="add2" /> </td> </tr> <tr> <td> <xsl:value-of select="add3" /> </td> </tr> <tr> <td> <xsl:value-of select="add4" /> </td> </tr> <tr> <td> <xsl:value-of select="region" /> </td> </tr> <tr> <td> <xsl:value-of select="country" /> </td> </tr> </table> </td> <td valign="top" width="200"> <table cellpadding="0" cellspacing="0" style="padding-right: 5px"> <tr> <td> <xsl:value-of select="phone1" /> </td> </tr> <tr> <td> <xsl:value-of select="phone2" /> </td> </tr> <tr> <td> <xsl:value-of select="phone3" /> </td> </tr> <tr> <td> <xsl:value-of select="fax" /> </td> </tr> </table> </td> </tr> <tr> <td valign="top"> <table cellpadding="0" cellspacing="0" style="padding-right: 5px"> <tr> <td> <xsl:value-of select="email1" /> </td> </tr> <tr> <td> <xsl:value-of select="email2" /> </td> </tr> <tr> <td> <xsl:value-of select="email3" /> </td> </tr> </table> </td> <td valign="top"> <table cellpadding="0" cellspacing="0" style="padding-right: 5px"> <tr> <td> <xsl:value-of select="web1" /> </td> </tr> <tr> <td> <xsl:value-of select="web2" /> </td> </tr> </table> </td> </tr> <tr> <td colspan="10" style="font-style: italic;"> <xsl:value-of select="notes" /> </td> </tr> </table> </td> </tr> </table> </xsl:template> </xsl:stylesheet>
|
||||
|
© 2003,2004, 1060® Research Limited
1060 registered trademark, NetKernel trademark of 1060 Research Limited
|
||||