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.
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)
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}'
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
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.
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.
Function MergeXMLFileXSLFile(ByVal XMLFile AsString, _
ByVal XSLFile AsString, _
ByVal ParamNames AsVariant, _
ByVal ParamValues AsVariant)
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 IntegerFor i = 0 ToUBound(ParamNames)
proc.addParameter ParamNames(i), ParamValues(i)
NextOn Error Resume Nextcall proc.Transform
If Err > 0 Then
MergeXMLFileXSLFile = Err.Description
Exit FunctionEnd If
MergeXMLFileXSLFile = proc.output
Set proc = NothingSet XSLTemplate = NothingSet XML = NothingSet XSL = NothingEnd 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):
<xsl:text disable-output-escaping="yes"><%</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
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:
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 . 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:
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: