--The following tcl script demonstrates how the XML file is generated:
####################
#
# Packages
#
####################
package require tclodbc
##
#
# Procedures
#
##
#
# Certain characters must be encoded in XML
#
proc Encode {str} {
#
# Standard encodings
#
set enc(&) {&}
set enc(<) {<}
set enc(>) {>}
set enc(\") {"}
#
# HACK ALERT
#
# Single quotes cause problems in SQL INSERT statements
#
set enc(') {''}
return [string map [array get enc] $str]
}
#
# Take an Access file and dump its contents to an XML file
#
proc XMLfromAccess {dbFile xmlFile} {
#
# Assume that we are converting Access files
#
set driver "Microsoft Access Driver (*.mdb)"
#
# Connect to db
#
database db "DRIVER=$driver;DBQ=$dbFile"
#
# Start XML file
#
lappend xml "<?xml version=\"1.0\"?>"
lappend xml "<ODBC file=\"$dbFile\">"
#
# Obtain the Schema details
#
lappend xml "\t<SCHEMA>"
foreach tableDef [db tables] {
set table(TABLE_QUALIFIER) [lindex $tableDef 0]
set table(TABLE_OWNER) [lindex $tableDef 1]
set table(TABLE_NAME) [lindex $tableDef 2]
set table(TABLE_TYPE) [lindex $tableDef 3]
set table(REMARKS) [lindex $tableDef 4]
#
# Only process normal tables
#
if {[string compare $table(TABLE_TYPE) TABLE]} {
continue
}
#
# TABLE tags start here
#
lappend xml "\t\t<TABLE name=\"$table(TABLE_NAME)\">"
foreach key [array names table] {
lappend xml "\t\t\t<$key>$table($key)</$key>"
}
foreach columnDef [db columns $table(TABLE_NAME)] {
set column(TABLE_QUALIFIER) [lindex $columnDef 0]
set column(TABLE_OWNER) [lindex $columnDef 1]
set column(TABLE_NAME) [lindex $columnDef 2]
set column(COLUMN_NAME) [lindex $columnDef 3]
set column(DATA_TYPE) [lindex $columnDef 4]
set column(TYPE_NAME) [lindex $columnDef 5]
set column(PRECISION) [lindex $columnDef 6]
set column(LENGTH) [lindex $columnDef 7]
set column(SCALE) [lindex $columnDef 8]
set column(RADIX) [lindex $columnDef 9]
set column(NULLABLE) [lindex $columnDef 10]
set column(REMARKS) [lindex $columnDef 11]
#
# COLUMN tags start here
#
lappend xml "\t\t\t<COLUMN name=\"$column(COLUMN_NAME)\">"
foreach key [array names column] {
lappend xml "\t\t\t\t<$key>$column($key)</$key>"
}
lappend xml "\t\t\t</COLUMN>"
}
unset column
foreach indexDef [db indexes $table(TABLE_NAME)] {
set index(TABLE_QUALIFIER) [lindex $indexDef 0]
set index(TABLE_OWNER) [lindex $indexDef 1]
set index(TABLE_NAME) [lindex $indexDef 2]
set index(NON_UNIQUE) [lindex $indexDef 3]
set index(INDEX_QUALIFIER) [lindex $indexDef 4]
set index(INDEX_NAME) [lindex $indexDef 5]
set index(TYPE) [lindex $indexDef 6]
set index(SEQ_IN_INDEX) [lindex $indexDef 7]
set index(COLUMN_NAME) [lindex $indexDef 8]
set index(COLLATION) [lindex $indexDef 9]
set index(CARDINALITY) [lindex $indexDef 10]
set index(PAGES) [lindex $indexDef 11]
set index(FILTER_CONDITION) [lindex $indexDef 12]
#
# INDEX tags
#
lappend xml "\t\t\t<INDEX name=\"$index(INDEX_NAME)\">"
foreach key [array names index] {
lappend xml "\t\t\t\t<$key>$index($key)</$key>"
}
lappend xml "\t\t\t</INDEX>"
}
unset index
lappend xml "\t\t</TABLE>"
}
unset table
lappend xml "\t</SCHEMA>"
#
# Obtain the Table data
#
lappend xml "\t<DATA>"
foreach tableDef [db tables] {
set table(TABLE_QUALIFIER) [lindex $tableDef 0]
set table(TABLE_OWNER) [lindex $tableDef 1]
set table(TABLE_NAME) [lindex $tableDef 2]
set table(TABLE_TYPE) [lindex $tableDef 3]
set table(REMARKS) [lindex $tableDef 4]
#
# Only process normal tables
#
if {[string compare $table(TABLE_TYPE) TABLE]} {
continue
}
#
# Execute SELECT
#
db statement data "SELECT * FROM $table(TABLE_NAME)"
data execute
#
# Save column specification
#
foreach colSpec [db columns $table(TABLE_NAME)] {
lappend typeList [lindex $colSpec 3]
lappend typeList [lindex $colSpec 5]
}
array set type $typeList
#
# Fetch each row
#
lappend xml "\t\t<TABLE name=\"$table(TABLE_NAME)\">"
while {[data fetch row]} {
lappend xml "\t\t\t<ROW>"
foreach key [array names row] {
lappend xml "\t\t\t\t<COLUMN name=\"$key\" type=\"$type($key)\">[Encode $row($key)]</COLUMN>"
}
lappend xml "\t\t\t</ROW>"
}
unset row
lappend xml "\t\t</TABLE>"
}
lappend xml "\t</DATA>"
lappend xml "</ODBC>"
#
# Write the XML file
#
set fp [open $xmlFile w]
puts $fp [join $xml "\n"]
close $fp
#
# Cleanup
#
db disconnect
}
##
#
# Main Program
#
##
foreach file [glob *.mdb] {
XMLfromAccess $file [file rootname $file].xml
}--The following example XSLT stylesheet shows how the tables and indexes can be created and the data loaded.<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <!-- Match the whole XML document --> <xsl:template match="/"> <xsl:apply-templates select="//SCHEMA/TABLE"/> <xsl:apply-templates select="//DATA/TABLE/ROW"/> </xsl:template> <!-- CREATE TABLE .. and call the INDEX template --> <xsl:template match="TABLE"> CREATE TABLE <xsl:value-of select="@name"/> (<xsl:apply-templates select="COLUMN" mode="schema_table"/>); <!-- Create all indexes associated with a table --> <xsl:apply-templates select="INDEX"/> </xsl:template> <!-- CREATE TABLE .. (?) --> <xsl:template match="COLUMN" mode="schema_table"> <xsl:value-of select="@name"/> <xsl:text> </xsl:text> <!-- Type matchings --> <xsl:choose> <xsl:when test="TYPE_NAME='COUNTER'">INTEGER</xsl:when> <xsl:otherwise><xsl:value-of select="TYPE_NAME"/></xsl:otherwise> </xsl:choose> <xsl:if test="position()!=last()">,</xsl:if> </xsl:template> <!-- CREATE INDEX .. --> <xsl:template match="INDEX"> <xsl:if test="string-length(@name)>0"> CREATE <xsl:choose><xsl:when test="NON_UNIQUE=0">UNIQUE</xsl:when></xsl:choose> INDEX <xsl:value-of select="INDEX_NAME"/> ON <xsl:value-of select="TABLE_NAME"/> (<xsl:value-of select="COLUMN_NAME"/>); </xsl:if> </xsl:template> <!-- INSERT INTO .. --> <xsl:template match="ROW"> INSERT INTO <xsl:value-of select="../@name"/> (<xsl:apply-templates select="COLUMN" mode="data_table_row1"/>) VALUES (<xsl:apply-templates select="COLUMN" mode="data_table_row2"/>); </xsl:template> <!-- INSERT INTO .. (?) --> <xsl:template match="COLUMN" mode="data_table_row1"> <xsl:value-of select="@name"/> <xsl:if test="position()!=last()">,</xsl:if> </xsl:template> <!-- INSERT INTO .. (..) VALUES (?) --> <xsl:template match="COLUMN" mode="data_table_row2"> <!-- Some types need to be quoted --> <xsl:choose> <xsl:when test="@type='CHAR'">'<xsl:value-of select="."/>'</xsl:when> <xsl:when test="@type='VARCHAR'">'<xsl:value-of select="."/>'</xsl:when> <xsl:otherwise><xsl:value-of select="."/></xsl:otherwise> </xsl:choose> <xsl:if test="position()!=last()">,</xsl:if> </xsl:template> </xsl:stylesheet>
[ Category Database | Category XML | ]

