BizTalk Utilities CV ,   Jobs ,   Code library  
 
Home Page
Uncategorized
Client-Side Presentation Logic
Learn XML
The Understanding XML Game
Dynamic functions: Functional combination, partial application and lambda expressions
An exploration of XML in database management systems
Code Samples 1
Code Samples 2
Using XML to manage a wizard
An enhancement of the Microsoft XML Class Generator
Format XML
Sending Binary Data in XML to server
Retrieving a Registry subtree as XML
An example of creating practical and efficient client-side, offline, standalone, server-independent
Using custom XML Namespaces in a VB application from an XML stylesheet
An XML Chat room
Base64 Encoder
A very simple way to generate multiple HTML combos from XML.
Retrieving a Registry subtree as XML
Retrieve Records
VB XML Parser
<< System.XML
WCF, WS, SOAP >>

By :Mark Wilson
I am the creator of TopXML. I am available for international and local (Australia) contracts. I am a Solution Architect/Business Analyst. I have worked in IT in several countries (NZ, Australia, South Africa, UK) building and training teams for government and very large non-governmental organizations. I am ex-Microsoft Consulting Services. I wrote the first book on Microsoft XML published in 2000 called XML Programming with VB and ASP. Most recently I have been building tools for the SEO industry. Ask me for a 37 point SEO health-checkup for your website.
First posted :06/11/2001
Times viewed :387

 

 

  

Database Web Application Wizard.

by Dmitriy Shapiro

 

  

Article sponsored by ITHorizons

It is a long road for any software company to efficiently migrate reusable components, frameworks, design features, code conventions etc. from one project to another. To make this road shorter programmers who are proficient with those reusable elements can write the "wizards" for the specific problem domain.

For example - Database Web Application. In most cases regardless of the nature of the data, applications have to perform common operations: View, Search, Sort, Add, Delete, Update Data. Those operations have to be repeated for almost every table in the database. In addition application can have common database access, security, error handling, mail notifications, concurrency control mechanisms. It would be nice if code for all those operations was created automatically, so a programmer can concentrate on implementing specific business rules and move on.

I would like to demonstrate how to start Database Web Application Wizard with:

  • Database catalog (meta-data, schema)

  • Reusable homegrown components (server-site includes for simplicity)

  • Extensible Markup Language (XML)

  • Extensible Stylesheet Language Transformations (XSLT)

  • Common well-known object models (OLE DB, MSXML Parser)

Application can be done in two stages

  1. Exporting the database schema into the XML Document
  2. Transforming the XML Document into the Active Server Pages with XSLT templates

You can find "Why XML and XSLT ?" section at the end of this article.

Exporting database schema into XML Document.

Our sample is an University Department database that links departments, students, instructors and courses.

PK - Primary Key
FK - Foreign Key
U - Unique Constrain

SQL Script for Tables in Department database

There are several methods to programmatically retrieve Meta information from the database:

Generic
  • Microsoft ActiveX Data Objects Extensions for Data Definition Language and Security (ADOX)
  • OpenSchema method of the ADO Connection Object
  • Retrieving meta-data thought ODBC and JDBC
Database specific
  • SQL Distributed Management Objects (SQL-DMO)  for Microsoft SQL Server
  • Oracle: select * from all_tables where owner = '{username}' smile.gif (862 bytes)

We use SQL-DMO Objects since we dealing with Microsoft SQL Server. Here are some fragments of the Visual Basic source code.
First we need to connect to an instance of Microsoft SQL Server.

Dim m_SQLServer As New SQLDMO.SQLServer2
m_SQLServer.Connect "localhost", username, password

Then retrieve a Department database 

Dim m_Database As SQLDMO.Database2
Set m_Database = m_SQLServer.Databases("Department")

Next step is get all user tables, fields, keys, constrains and create an XML Document (database.xml).
Create <Tables> Element and append it with <Table> Elements for each User Table (SQLDMOObj_UserTable ).

Dim tbl As SQLDMO.Table2
Set m_xmlDoc = New DOMDocument
Set TablesElement = m_xmlDoc.createElement("Tables")
For Each tbl In m_Database.Tables
    If tbl.TypeOf = SQLDMOObj_UserTable Then
       TablesElement.appendChild GetTableElement(tbl)
    End If
Next
Set m_xmlDoc.documentElement = TablesElement

Add Name attribute to the  <Table> Element.

Set TableElement = m_xmlDoc.createElement("Table")
TableElement.setAttribute "Name", tbl.Name

Create <Fields> Element and append it with <Field> Elements. 
Add <Fields> Element to <Table> Element.

Dim clm As SQLDMO.Column2
Set
FieldsElement = m_xmlDoc.createElement("Fields")
For Each clm In tbl.Columns
       FieldsElement.appendChild GetFieldElement(clm, tbl.keys)
Next
TableElement.appendChild FieldsElement

Each <Field> Element contains 

  • requered attributes: Name, Type, Length and AllowNulls 
  • optional attributes: IsForeignKey, ReferencedTable, ReferencedField, UniqueField
FieldElement.setAttribute "Name", clm.Name
FieldElement.setAttribute "Type", clm.dataType
FieldElement.setAttribute "Length", clm.length
FieldElement.setAttribute "AllowNulls", IIf(clm.AllowNulls, "Yes", "No")
For Each key In keys
       If key.Type = SQLDMOKey_Foreign Then
           For Each keyColumn In key.KeyColumns
                  If keyColumn = clm.Name Then
                     FieldElement.setAttribute "IsForeignKey", "Yes"
                     FieldElement.setAttribute "ReferencedTable", key.ReferencedTable
                     FieldElement.setAttribute "ReferencedField", key.ReferencedColumns(1)
                 End If
           Next
       End If
       If
key.Type = SQLDMOKey_Unique Then
           For Each keyColumn In key.KeyColumns
                  If keyColumn = clm.Name Then
                     FieldElement.setAttribute "UniqueField", "Yes"
                  End If
           Next
       End If
Next

This is a fragment of the generated XML Document (database.xml) for the Student Table. 

    <Table Name="Course">
      <Fields>
        <Field Name="idCourse" Type="int" Length="4" AllowNulls="No" InPrimaryKey="Yes" Identity="Yes"/>                                  <Field Name="idDepartment" Type="int" Length="4" AllowNulls="No" IsForeignKey="Yes" 
                  ReferencedTable="Department" 
ReferencedField="idDepartment"/>
         <Field Name="idInstructor" Type="int" Length="4" AllowNulls="No" IsForeignKey="Yes" 
                  ReferencedTable="Instructor" ReferencedField="idInstructor"
/>
        <Field Name="Name" Type="char" Length="50" AllowNulls="No" UniqueField="Yes"/>
        <Field Name="CreditHours" Type="int" Length="4" AllowNulls="No"/>
      </Fields>
    </Table>

Transforming the XML Document into the ASP with XSLT templates

Once we have database as XML, we can apply XSLT Templates to generate Active Server Pages for the specific database operations. In order to do it we use  MergeXMLFileXSLFile function.

MergeXMLFileXSLFile function
Function MergeXMLFileXSLFile(ByVal XMLFile As String, _
                                ByVal XSLFile As String, _
                                ByVal ParamNames As Variant, _
                                ByVal ParamValues As Variant)
    Dim proc As IXSLProcessor
    Dim XML As FreeThreadedDOMDocument
    Dim XSL As FreeThreadedDOMDocument
    Dim XSLTemplate As XSLTemplate
    Set XML = CreateObject("MSXML2.FreeThreadedDOMDocument")
    Set XSL = CreateObject("MSXML2.FreeThreadedDOMDocument")
    XML.Load XMLFile
    XSL.Load XSLFile
    Set XSLTemplate = CreateObject("MSXML2.XSLTemplate")
    XSLTemplate.stylesheet = XSL
    Set proc = XSLTemplate.createProcessor()
    proc.input = XML
    Dim i As Integer
    For i = 0 To UBound(ParamNames)
        proc.addParameter ParamNames(i), ParamValues(i)
    Next
    On Error Resume Next
    call proc.Transform
    If Err > 0 Then
        MergeXMLFileXSLFile = Err.Description
        Exit Function
    End If
    MergeXMLFileXSLFile = proc.output
    Set proc = Nothing
    Set XSLTemplate = Nothing
    Set XML = Nothing
    Set XSL = Nothing
End Function

 

Operations that can be automated based on database schema
  • Add, Delete, Update, View, Search, Navigate and Sort Records 
  • Access to the children and parents for each Table
Business rules that can be added manually, or throug the project meta-data (may be described in the next article)
  • Student cannot have more than 5 courses
  • At least 50% of all courses have to be in the same department that Student belongs
  • Course cannot have more than 5 credit hours
  • Instructor cannot have more than 5 courses, etc…

Each operation has corresponding XSLT template. Let's have a look at TableToAddForm.xsl (source code). It contains instructions to create an Add Form, that allows user to enter the new data into the table. Call to MergeXMLFileXSLFile( "Database.xml", "TableToAddForm.xsl", Array("Table"), Array("Student")) returns text for StudentAddFrm.asp Active Server Page. This page (link will bring you to the code section):

As template went through the Field Elements, it applied instructions which are common for all Tables

<?xml version="1.0"?>
  <xsl:stylesheet version="1.0">
    <xsl:output method="html" indent="yes" omit-xml-declaration="yes"/>
    <xsl:param name="Table"/>
    <xsl:template match="/" xml:space="preserve">
     
      <xsl:comment>#include file ="../Include/DBManager.inc"</xsl:comment>
      <xsl:comment>#include file ="../Include/Utilities.inc"</xsl:comment>
     
      <html>       
        <body>         
          <b>
            Add new
            <xsl:value-of select="$Table"/>
          </b>
         
          <form method="POST">
            <xsl:attribute name="action">
              <xsl:value-of select="$Table"/>
              Add.asp
            </xsl:attribute>
           
            <table border="0" cellSpacing="1" width="100%">             
              <xsl:apply-templates select="//Table[@Name=$Table]/Fields/Field">
                <xsl:sort select="@IsForeignKey"/>
              </xsl:apply-templates>             
            </table>
           
            <input id="submit1" name="submit1" style="LEFT: 10px; TOP: 146px" type="submit" value="Submit"/>
            <input id="reset1" name="reset1" type="reset" value="Reset"/>
 
         
            <p>
              <b>
                <font color="red">*</font>
              </b>
              Required
            </p>
            &#160;
          </form>         
        </body>       
      </html>
    </xsl:template>

    <xsl:template match="Field[not(@Identity) or @Identity='No']">
      <tr>
        <td width="20%">
          <xsl:value-of select="@Name"/>
        </td>
        <td width="5%" align="right">
          <xsl:if test="@AllowNulls = 'No'">
            <b>
              <font color="red">*</font>
            </b>
          </xsl:if>
 
      </td>
        <td width="35%">
          <xsl:call-template name="showField"/>
        </td>
        <td width="40%"/>
      </tr>
    </xsl:template>

    <xsl:template name="showField">
      <xsl:choose>
        <xsl:when test="@IsForeignKey">
          <xsl:variable name="ReferencedTable" select="@ReferencedTable"/>
          <xsl:text disable-output-escaping="yes">
            &lt;
          </xsl:text>
          % Response.Write ShowSelect(&quot;SELECT
          <xsl:value-of select="@ReferencedField"/>
          ,
          <xsl:value-of select="//Table[@Name=$ReferencedTable]/Fields/Field[@UniqueField]/@Name"/>
          FROM  <xsl:value-of select="@ReferencedTable"/>","
          "<xsl:value-of select="@Name"/>",
         "
<xsl:value-of select="//Table[@Name=$ReferencedTable]/Fields/Field[@UniqueField]/@Name"/>",
         "",FALSE) %

          <xsl:text disable-output-escaping="yes">&gt;</xsl:text>
        </xsl:when>
        <xsl:otherwise>
          <input>
            <xsl:attribute name="name">
              <xsl:value-of select="@Name"/>
            </xsl:attribute>
            <xsl:attribute name="value"/>
            <xsl:attribute name="maxlength">
              <xsl:value-of select="@Length"/>
            </xsl:attribute>
            <xsl:attribute name="size">
              30
            </xsl:attribute>
          </input>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:template>
  </xsl:stylesheet>

Output screen generated by StudentAddFrm.asp  

Sample project also contains template TableToAddPage.xsl (source) for an Active Server Page  that validates data 
and puts them into the database. Please note that it reports an Error if a Required Field is empty

<?xml version="1.0"?>
  <xsl:stylesheet version="1.0">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:param name="Table">
      Instructor
    </xsl:param>
    <xsl:template match="/">
      <xsl:comment>#include file ="../Include/DBManager.inc&quot;</xsl:comment>
      <xsl:comment>#include file ="../Include/Utilities.inc"</xsl:comment>

      <xsl:text disable-output-escaping="yes">&lt;%</xsl:text>
      Sub ShowMessage(byVal szMessage) 
        Response.Write "
<html><body><b>" + szMessage + "</b></body></html>" 
        End Sub 

       const ErrorMessage = "Null value was supplied for a non-nullable field: " 
       
       'Define local variable for all not identity Fields

      <xsl:for-each select="//Table[@Name=$Table]/Fields/Field[not(@Identity)]">
        Dim l_<xsl:value-of select="@Name"/>
      </xsl:for-each>

      'Retrieve all Parameters
      <xsl:for-each select="//Table[@Name=$Table]/Fields/Field[not(@Identity) or (@Identity = 'No')]">
        l_<xsl:value-of select="@Name"/>  = Request.Form("<xsl:value-of select="@Name"/>")
      </xsl:for-each>

      'Validate all Non-nullable Parameters
      <xsl:for-each select="//Table[@Name=$Table]/Fields/Field[@AllowNulls='No' and (not(@Identity) or (@Identity = 'No'))]">
        if l_<xsl:value-of select="@Name"/> = "" 
        Then 
          call ShowMessage(ErrorMessage + "
<xsl:value-of select="@Name"/>"
          Response.End 
       end if

      </xsl:for-each>

      'Check value for all Nullable Parameters
      <xsl:for-each select="//Table[@Name=$Table]/Fields/Field[@AllowNulls='Yes']">
        if l_<xsl:value-of select="@Name"/> = "" Then 
          l_
<xsl:value-of select="@Name"/>= Null
      </xsl:for-each>

      'Add Record to the Database 
      On Error Resume Next 
      Dim RS 
      Set RS = CreateObject("ADODB.Recordset") 
      RS.CursorLocation = adUseClient 
      RS.Open "
<xsl:value-of select="$Table"/>" , Session("szConnectionString"), adOpenStatic, adLockOptimistic, adCmdTable 
      RS.AddNew

      <xsl:for-each select="//Table[@Name=$Table]/Fields/Field[not(@Identity) or (@Identity = 'No')]">
        RS("<xsl:value-of select="@Name"/>") = l_<xsl:value-of select="@Name"/>
      </xsl:for-each>
      RS.Update 
      RS.Close 
      Set RS = Nothing 
      If not Err.Number = 0 Then 
        call ShowMessage(Err.Description) 
      Else 
        call ShowMessage("
<xsl:value-of select="$Table"/> was added successfully.") 
      End If

      <xsl:text disable-output-escaping="yes">%&gt;</xsl:text>
    </xsl:template>

  </xsl:stylesheet>

Why XML and XSLT ?

I think the answer here is the potential, plus it is fun to work with. XSLT technology is here to stay and it is much more stable than a year ago. I admit that this is not the friendliest language, and there is no developer studio that allows you to debug it. But the language fits nicely with its ability to transform XML documents. And tools are coming (look for XSLT debugger), since the technology is gaining in popularity. 

I expect one day we will see an XML version of data definition language (DDL), so we can skip Exporting the database schema into the XML Document, and adjust scripts to standard Database XML Schema. Once in XML, the database schema can be integrated with other documents and can be transformed into all sorts of useful applications. 

Example 1: Localization

When we display information, we label it with the appropriate titles. Often these titles correspond to names of the underlying tables and fields. Why don't we extract all the table and field names into the separate XML Document (Titles.xml) and change the default titles for tables and fields:

<Field>
<Name>DepartmentNumber</Name>
    <Titles>
        <English>Department Number</English>
    </Titles>
</Field>

Then we can send this document to a third party agency for translation to Spanish, French, German and Italian. Of course they would not accept it, if it was not in XML form smile.gif (862 bytes). Then the final output document will contain all appropriate titles:

<Field>
    <Name>DepartmentNumber</Name>
    <Titles>
        <English>Department Number</English>
        <Spanish>Nú­¥²¯ Del Departamento</Spanish>
        <French>Nombre De Service</French>
        <German>Abteilung Zahl</German>
        <Italian>Numero Di Reparto</Italian>
    </Titles>
</Field>

Now, when we display "DepartmentNumber", we can substitute this word with the appropriate title on a given language.

Example 2: Validation Rules 

Let's say we have product management give us all requirements in XML form. So, for Department Number they may look like this:

<Field>
    <Name>DepartmentNumber</Name>
    <Validation>
        <MinSize>3</MinSize>
        <CharType>notNumbers</CharType>
    </Validation>
</Field>

In the template that responsible for making update or add pages, check Validation Rules for any field. If the rule exists then write a special code to handle it.

Where to go ?

Wizards are most efficient on the initial stage of the project. They give you a framework that inherits previous project experience. You can build your own or get it from a third party. No matter what technology you use, any investments into the wizard will bring you benefits. Here are some tools that provide Database Web Application wizards:

Status Tool Vendor Comments
Well known Microsoft Visual Interdev Microsoft  
Macromedia Dreamweaver UltraDev Macromedia  
COM Express Shoutsoft  
New XSL Web Wizard IT Horizons Our company made this one. Check it out !

Good luck.

 

  

Rate this article on a scale of 1 to 10

Your vote :  


 

Recent Jobs

Sr. Software Engineer - Analytics
Immediate Mainframe openings for Ch
Immediate TANDEM-TAL openings for C
Immediate ASP.NET/C# Openings for C
Sr. Software Engineer

View all Jobs (Add yours)
View all CV (Add yours)



United Kingdom Conference Calling
water softener
Teleconference
Host Department NOLIMIT Web Hosting
MSN
sunglasses
online fax


    Email TopXML  

Front Page Daily Stuff TopXML Forum XML blogs XML Newsgroups BizTalk Biztalk Utilities Biztalk Utilities Tutorial B2B SAP XML Microsoft .NET Dotnet System XML Soapformatter SQLXML XMLserializer XQuery PHP PHP SimpleXML PHP XML Dom PHP XML RPC PHP XSLT Java Java Java XML Xalan Microsoft ASP ASP Schemas XML SQL Server XML XMLDom XSL XSL Tutorial XSLT Stylesheets General Javascript CSS XHTML WAP