 --The following tcl script demonstrates how the XML file is generated:
--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 | ]

