Przeglądaj źródła

- DB Schema generator, conversion stylesheets for dbtext, mysql, postgres,
and oracle

Jan Janak 20 lat temu
rodzic
commit
47f139b038

+ 195 - 0
doc/stylesheets/dbschema/xsl/common.xsl

@@ -0,0 +1,195 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'>
+    
+    <xsl:key name="column_id" match="column" use="@id|xml:id"/>
+
+    <xsl:param name="prefix" select="."/>
+
+    <xsl:variable name="sign-prefix">unsigned </xsl:variable>
+    
+    <!-- Do not output text -->
+    <xsl:template match="text()|@*"/>
+    <xsl:template match="text()|@*" mode="drop"/>
+
+    <!-- Return the name of the context element, first look for a database
+         specific name, use the common name if no database-specific name
+         is found.
+    -->
+    <xsl:template name="get-name">
+	<xsl:param name="select" select="."/>
+	<xsl:choose>
+	    <!-- override test -->
+	    <xsl:when test="count($select/db:name)='1'">
+		<xsl:value-of select="normalize-space($select/db:name)"/>
+	    </xsl:when>
+	    <!-- No override, use the standard name -->
+	    <xsl:otherwise>
+		<xsl:value-of select="normalize-space($select/name)"/>
+	    </xsl:otherwise>
+	</xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="type-error">
+	<xsl:message terminate="yes">
+	    <xsl:text>ERROR: Table: </xsl:text>
+	    <xsl:value-of select="normalize-space(parent::table/name)"/>
+	    <xsl:text>, column: </xsl:text>
+	    <xsl:value-of select="normalize-space(name)"/>
+	    <xsl:text> - unsupported column type: </xsl:text>
+	    <xsl:value-of select="normalize-space(type)"/>
+	    <xsl:text>.</xsl:text>
+	</xsl:message>
+    </xsl:template>
+
+    <!-- Process the root database element -->
+    <xsl:template match="/">
+	<!-- Process only the first database element, this is supposed to be
+	     the root database element and having multiple database elements is
+	     a bug
+	-->
+	<xsl:apply-templates select="database[1]"/>
+    </xsl:template>
+
+    <!-- ################ DATABASE ################# -->
+
+    <xsl:template match="database">
+
+	<!-- Create all tables -->
+	<xsl:apply-templates select="table"/>
+    </xsl:template>
+
+    <!-- ################ /DATABASE ################# -->
+
+    <!-- ################ TABLE ################# -->
+
+    <xsl:template match="table">
+	<!-- Process all columns -->
+	<xsl:apply-templates select="column"/>
+
+	<!-- Process all indexes -->
+	<xsl:apply-templates select="index"/>
+
+	<!-- Process initial data --> 
+	<xsl:apply-templates select="row"/>
+    </xsl:template>
+
+    <!-- ################ /TABLE ################# -->
+
+    <!-- ################ COLUMN ################# -->
+    
+    <xsl:template match="column"/>
+
+    <xsl:template name="get-type-string">
+	<xsl:param name="select" select="."/>
+	<xsl:choose>
+	    <xsl:when test="count($select/db:type)='1'">
+		<xsl:value-of select="translate(normalize-space($select/db:type),
+		  'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
+	    </xsl:when>
+	    <xsl:otherwise>
+		<xsl:value-of select="translate(normalize-space($select/type),
+		  'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
+	    </xsl:otherwise>
+	</xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="get-type">
+	<xsl:param name="select" select="."/>
+	<xsl:variable name="type">
+	    <xsl:call-template name="get-type-string">
+		<xsl:with-param name="select" select="$select"/>
+	    </xsl:call-template>
+	</xsl:variable>
+	<xsl:choose>
+	    <xsl:when test="starts-with($type, $sign-prefix)">
+		<xsl:value-of select="substring-after($type, $sign-prefix)"/>
+	    </xsl:when>
+	    <xsl:otherwise>
+		<xsl:value-of select="$type"/>
+	    </xsl:otherwise>
+	</xsl:choose>
+    </xsl:template>
+    
+    <xsl:template name="get-sign">
+	<xsl:param name="select" select="."/>
+	<xsl:variable name="type">
+	    <xsl:call-template name="get-type-string">
+		<xsl:with-param name="select" select="$select"/>
+	    </xsl:call-template>
+	</xsl:variable>
+	<xsl:choose>
+	    <xsl:when test="starts-with($type, $sign-prefix)">0</xsl:when>
+	    <xsl:otherwise>1</xsl:otherwise>
+	</xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="get-null">
+	<xsl:param name="select" select="."/>
+	<xsl:choose>
+	    <xsl:when test="count($select/db:null)='1'">1</xsl:when>
+	    <xsl:when test="count($select/null)='1'">1</xsl:when>
+	    <xsl:otherwise>0</xsl:otherwise>
+	</xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="get-size">
+	<xsl:param name="select" select="."/>
+	<xsl:choose>
+	    <xsl:when test="count($select/db:size)='1'">
+		<xsl:value-of select="normalize-space($select/db:size)"/>
+	    </xsl:when>
+	    <xsl:otherwise>
+		<xsl:value-of select="normalize-space($select/size)"/>
+	    </xsl:otherwise>
+	</xsl:choose>
+    </xsl:template>
+
+    <!-- ################ /COLUMN ################# -->
+
+    <!-- ################ INDEX ################# -->
+
+    <xsl:template match="index">
+	<xsl:apply-templates match="colref"/>
+    </xsl:template>
+    
+    <!-- ################ /INDEX ################# -->
+
+    <!-- ################ COLREF ################# -->
+
+    <xsl:template match="colref"/>
+
+    <xsl:template name="get-column">
+	<xsl:param name="id" select="/.."/>	
+	<xsl:variable name="columns" select="key('column_id', $id)"/>
+	<xsl:variable name="column" select="$columns[1]"/>
+
+	<xsl:choose>
+	    <xsl:when test="count($column) = 0">
+		<xsl:message terminate="yes">
+		    <xsl:text>ERROR: Column with id '</xsl:text>
+		    <xsl:value-of select="$id"/>
+		    <xsl:text>' does not exist.</xsl:text>
+		</xsl:message>
+	    </xsl:when>
+	    <xsl:otherwise>
+		<xsl:copy-of select="$column"/>
+	    </xsl:otherwise>
+	</xsl:choose>
+    </xsl:template>
+
+    <!-- ################ /COLREF ################# -->
+
+    <!-- ################ ROW ################# -->
+
+    <xsl:template match="row">
+	<xsl:apply-templates select="value"/>
+    </xsl:template>
+
+    <!-- ################ /ROW ################# -->
+
+    <!-- ################ VALUE ################# -->
+
+    <xsl:template match="value"/>
+
+    <!-- ################ /VALUE ################# -->
+</xsl:stylesheet>

+ 149 - 0
doc/stylesheets/dbschema/xsl/dbtext.xsl

@@ -0,0 +1,149 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version='1.0'
+                xmlns:xi="http://www.w3.org/2001/XInclude"
+                xmlns:db="http://iptel.org/dbschema/dbtext">
+
+    <xsl:import href="common.xsl"/>
+    <xsl:output method="text" indent="no" omit-xml-declaration="yes"/>
+
+    <!-- Create the file for the table in dbtext subdirectory -->
+    <xsl:template match="table">
+	<xsl:variable name="name">
+	    <xsl:call-template name="get-name"/>
+	</xsl:variable>
+	
+	<xsl:variable name="path" select="concat($prefix, concat('/', $name))"/>
+	<xsl:document 
+	    href="{$path}"
+	    method="text"
+	    indent="no"
+	    omit-xml-declaration="yes">
+		<xsl:apply-imports/>
+	</xsl:document>
+    </xsl:template>
+
+    <!-- Create column definitions -->
+    <xsl:template match="column">
+	<xsl:variable name="type">
+	    <xsl:call-template name="get-type"/>
+	</xsl:variable>
+
+	<xsl:variable name="null">
+	    <xsl:call-template name="get-null"/>
+	</xsl:variable>
+
+	<xsl:call-template name="get-name"/>
+	<xsl:text>(</xsl:text>
+	<xsl:choose>
+	    <xsl:when test="$type='char' or 
+		            $type='short' or 
+                            $type='int' or
+	                    $type='long' or 
+                            $type='datetime'">
+		<xsl:text>int</xsl:text>
+	    </xsl:when>
+	    <xsl:when test="$type='float' or 
+		            $type='double'">
+		<xsl:text>double</xsl:text>
+	    </xsl:when>
+	    <xsl:when test="$type='string' or 
+                            $type='binary'">
+		<xsl:text>str</xsl:text>
+	    </xsl:when>
+	    <xsl:otherwise>
+		<xsl:call-template name="type-error"/>
+	    </xsl:otherwise>
+	</xsl:choose>
+
+	<xsl:if test="$null=1">
+	    <xsl:text>,null</xsl:text>
+	</xsl:if>
+	<xsl:text>) </xsl:text>
+	<xsl:if test="position()=last()">
+	    <xsl:text>&#x0A;</xsl:text>
+	</xsl:if>
+    </xsl:template>
+
+    <!-- Escape all : occurrences -->
+    <xsl:template name="escape">
+	<xsl:param name="value"/>
+	<xsl:choose>
+	    <xsl:when test="contains($value, ':')">
+		<xsl:value-of select="concat(substring-before($value, ':'), '\:')"/>
+		<xsl:call-template name="escape">
+		    <xsl:with-param name="value" select="substring-after($value, ':')"/>
+		</xsl:call-template>
+	    </xsl:when>
+	    <xsl:otherwise>
+		<xsl:value-of select="$value"/>
+	    </xsl:otherwise>
+	</xsl:choose>
+    </xsl:template>
+
+    <!-- Process initial data -->
+    <xsl:template match="row">
+	<!-- store the actual row so that it can be used later 
+	     with another context node 
+	-->
+	<xsl:variable name="row" select="."/>
+
+	<!-- Walk through all the columns of the table and lookup
+	     corresponding values based on id-col match from the
+             current row, use the default value of the column if
+	     there is no value with matching col attribute in the
+             current row
+	-->
+	<xsl:for-each select="parent::table/column">
+	    <xsl:variable name="id" select="@id"/>
+	    <xsl:call-template name="escape">
+		<xsl:with-param name="value">
+		    <xsl:choose>
+			<!-- If we have db-specific value, use it -->
+			<xsl:when test="$row/db:value[@col=$id]">
+			    <xsl:value-of select="normalize-space($row/db:value[@col=$id])"/>
+			</xsl:when>
+			<!-- No db-specific value, try generic -->
+			<xsl:when test="$row/value[@col=$id]">
+			    <xsl:value-of select="normalize-space($row/value[@col=$id])"/>
+			</xsl:when>
+			<!-- No value at all, try db-specific default value for the column -->
+			<xsl:when test="db:default">
+			    <xsl:value-of select="normalize-space(db:default)"/>
+			</xsl:when>
+			<!-- Try generic default value for the column -->
+			<xsl:when test="default">
+			    <xsl:value-of select="normalize-space(default)"/>
+			</xsl:when>
+			<!-- No value and no default value for the column - ouch -->
+			<xsl:otherwise>
+			    <xsl:message terminate="yes">
+				<xsl:text>ERROR: Value for column </xsl:text>
+				<xsl:value-of select="normalize-space(name)"/>
+				<xsl:text> in table </xsl:text>
+				<xsl:value-of select="normalize-space(parent::table/name)"/>
+				<xsl:text> was not provided and the column has no default value.</xsl:text>
+			    </xsl:message>
+			</xsl:otherwise>
+		    </xsl:choose>
+		</xsl:with-param>
+	    </xsl:call-template>
+		
+	    <xsl:if test="not(position()=last())">
+		<xsl:text>:</xsl:text>
+	    </xsl:if>
+	</xsl:for-each>
+
+	<xsl:apply-imports/>
+	<xsl:text>&#x0A;</xsl:text>
+    </xsl:template>
+
+    <!-- Make sure all values reference existing columns -->
+    <xsl:template match="value">
+	<xsl:variable name="column">
+	    <xsl:call-template name="get-column">
+		<xsl:with-param name="id" select="@col"/>
+	    </xsl:call-template>
+	</xsl:variable>
+    </xsl:template>
+</xsl:stylesheet>

+ 23 - 0
doc/stylesheets/dbschema/xsl/docbook.xsl

@@ -0,0 +1,23 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version='1.0'
+                xmlns:db="http://iptel.org/dbschema/docbook"
+>
+    <xsl:import href="common.xsl"/>
+
+    <xsl:template match="/">
+	<xsl:variable name="filename" select="concat($prefix, concat('/', 'dbschema.xml'))"/>
+	<xsl:document href="{$filename}" method="xml" indent="yes"
+	    omit-xml-declaration="no">
+	    <xsl:element name="section">
+		<xsl:element name="title">
+		    <xsl:call-template name="get-name">
+			<xsl:with-param name="select" select="database[1]"/>
+		    </xsl:call-template>
+		</xsl:element>
+		<xsl:apply-templates select="/database[1]"/>
+	    </xsl:element>
+	</xsl:document>
+    </xsl:template>
+
+</xsl:stylesheet>

+ 95 - 0
doc/stylesheets/dbschema/xsl/mysql.xsl

@@ -0,0 +1,95 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version='1.0'
+                xmlns:db="http://iptel.org/dbschema/mysql"
+>
+
+    <xsl:import href="sql.xsl"/>
+
+    <xsl:template name="table.close">
+	<xsl:text>)</xsl:text>
+	<xsl:if test="db:type">
+	    <xsl:text> Type=</xsl:text>
+	    <xsl:value-of select="normalize-space(db:type)"/>
+	</xsl:if>
+	<xsl:text>;&#x0A;&#x0A;</xsl:text>	
+    </xsl:template>
+
+    <xsl:template name="column.type">
+	<xsl:variable name="type">
+	    <xsl:call-template name="get-type"/>
+	</xsl:variable>
+
+	<xsl:choose>
+	    <xsl:when test="db:type">
+		<xsl:value-of select="normalize-space(db:type)"/>
+	    </xsl:when>
+	    <xsl:when test="$type='char'">
+		<xsl:text>TINYINT</xsl:text>
+	    </xsl:when>
+	    <xsl:when test="$type='short'">
+		<xsl:text>SMALLINT</xsl:text>
+	    </xsl:when>
+	    <xsl:when test="$type='int'">
+		<xsl:text>INT</xsl:text>
+	    </xsl:when>
+	    <xsl:when test="$type='long'">
+		<xsl:text>BIGINT</xsl:text>
+	    </xsl:when>
+	    <xsl:when test="$type='datetime'">
+		<xsl:text>DATETIME</xsl:text>
+	    </xsl:when>
+	    <xsl:when test="$type='double'">
+		<xsl:text>DOUBLE</xsl:text>
+	    </xsl:when>
+	    <xsl:when test="$type='float'">
+		<xsl:text>FLOAT</xsl:text>
+	    </xsl:when>
+	    <xsl:when test="$type='string'">
+		<xsl:text>VARCHAR</xsl:text>
+	    </xsl:when>
+	    <xsl:when test="$type='binary'">
+		<xsl:text>BLOB</xsl:text>
+	    </xsl:when>
+	    <xsl:otherwise>
+		<xsl:call-template name="type-error"/>
+	    </xsl:otherwise>
+	</xsl:choose>
+    </xsl:template>
+
+    <xsl:template name="column.sign">
+	<xsl:variable name="signed">
+	    <xsl:call-template name="get-sign"/>
+	</xsl:variable>
+	
+	<xsl:if test="$signed = 0">
+	    <xsl:text> UNSIGNED</xsl:text>
+	</xsl:if>
+    </xsl:template>
+
+    <xsl:template match="index">
+	<xsl:variable name="index.name">
+	    <xsl:call-template name="get-name"/>
+	</xsl:variable>
+
+	<xsl:if test="position()=1">
+	    <xsl:text>,&#x0A;</xsl:text>
+	</xsl:if>
+	<xsl:text>    </xsl:text>
+	<xsl:if test="unique">
+	    <xsl:text>UNIQUE </xsl:text>
+	</xsl:if>
+	<xsl:text>KEY </xsl:text>
+	<xsl:if test="not($index.name='')">
+	    <xsl:value-of select="concat($index.name, ' ')"/>
+	</xsl:if>
+	<xsl:text>(</xsl:text>
+	<xsl:apply-templates select="colref"/>
+	<xsl:text>)</xsl:text>
+	<xsl:if test="not(position()=last())">
+	    <xsl:text>,</xsl:text>
+	    <xsl:text>&#x0A;</xsl:text>
+	</xsl:if>
+    </xsl:template>
+
+</xsl:stylesheet>

+ 9 - 0
doc/stylesheets/dbschema/xsl/oracle.xsl

@@ -0,0 +1,9 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version='1.0'
+                xmlns:xi="http://www.w3.org/2001/XInclude"
+                xmlns:db="http://iptel.org/dbschema/oracle">
+
+    <xsl:import href="sql.xsl"/>
+
+</xsl:stylesheet>

+ 11 - 0
doc/stylesheets/dbschema/xsl/postgres.xsl

@@ -0,0 +1,11 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version='1.0'
+                xmlns:xi="http://www.w3.org/2001/XInclude"
+                xmlns:db="http://iptel.org/dbschema/postgres"
+>
+
+    <xsl:import href="sql.xsl"/>
+
+</xsl:stylesheet>
+

+ 281 - 0
doc/stylesheets/dbschema/xsl/sql.xsl

@@ -0,0 +1,281 @@
+<?xml version='1.0'?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                version='1.0'
+>
+
+    <xsl:import href="common.xsl"/>
+
+    <xsl:template match="/">
+	<xsl:variable name="createfile" select="concat($prefix, concat('/', 'create.sql'))"/>
+	<xsl:document href="{$createfile}" method="text" indent="no" omit-xml-declaration="yes">
+	    <xsl:apply-templates select="/database[1]"/>
+	</xsl:document>
+
+	<xsl:variable name="dropfile" select="concat($prefix, concat('/', 'drop.sql'))"/>
+	<xsl:document href="{$dropfile}" method="text" indent="no" omit-xml-declaration="yes">
+	    <xsl:apply-templates mode="drop" select="/database[1]"/>
+	</xsl:document>
+    </xsl:template>
+
+<!-- ################ DATABASE ################# -->
+
+    <xsl:template match="database">
+	<xsl:variable name="database.name">
+	    <xsl:call-template name="get-name"/>
+	</xsl:variable>
+
+	<xsl:text>CREATE DATABASE </xsl:text>
+	<xsl:value-of select="$database.name"/>
+	<xsl:text>;&#x0A;</xsl:text>
+
+	<xsl:text>USE </xsl:text>
+	<xsl:value-of select="$database.name"/>
+	<xsl:text>;&#x0A;&#x0A;</xsl:text>
+
+	<xsl:apply-imports/>
+    </xsl:template>
+
+    <xsl:template match="database" mode="drop">
+	<xsl:variable name="database.name">
+	    <xsl:call-template name="get-name"/>
+	</xsl:variable>
+
+	<xsl:text>USE </xsl:text>
+	<xsl:value-of select="$database.name"/>
+	<xsl:text>;&#x0A;&#x0A;</xsl:text>
+	<xsl:apply-templates mode="drop" select="table"/>
+	<xsl:text>&#x0A;</xsl:text>
+	<xsl:text>DROP DATABASE </xsl:text>
+	<xsl:value-of select="$database.name"/>
+	<xsl:text>;&#x0A;</xsl:text>
+    </xsl:template>
+    
+<!-- ################ /DATABASE ################# -->
+
+    
+<!-- ################ TABLE  ################# -->
+    
+    <xsl:template match="table">
+	<xsl:variable name="table.name">
+	    <xsl:call-template name="get-name"/>
+	</xsl:variable>
+
+	<xsl:text>CREATE TABLE </xsl:text>
+	<xsl:value-of select="$table.name"/>
+	<xsl:text> (&#x0A;</xsl:text>
+
+	<!-- Process all columns -->
+	<xsl:apply-templates select="column"/>
+
+	<!-- Process all indexes -->
+	<xsl:apply-templates select="index"/>
+
+	<xsl:text>&#x0A;</xsl:text>
+
+	<xsl:call-template name="table.close"/>
+
+	<!-- Process initial rows of data -->
+	<xsl:apply-templates select="row"/>
+    </xsl:template>
+
+    <xsl:template match="table" mode="drop">
+	<xsl:text>DROP TABLE </xsl:text>
+	<xsl:call-template name="get-name"/>
+	<xsl:text>;&#x0A;</xsl:text>
+    </xsl:template>
+
+    <xsl:template name="table.close">
+	<xsl:text>);&#x0A;&#x0A;</xsl:text>
+    </xsl:template>
+
+<!-- ################ /TABLE ################  -->
+
+<!-- ################ COLUMN ################  -->
+
+    <xsl:template match="column">
+	<xsl:text>    </xsl:text>
+	<xsl:call-template name="get-name"/>
+	<xsl:text> </xsl:text>
+
+	<xsl:call-template name="column.type"/>
+
+	<xsl:call-template name="column.size"/>
+
+	<xsl:call-template name="column.sign"/>
+
+	<xsl:variable name="null">
+	    <xsl:call-template name="get-null"/>
+	</xsl:variable>
+	<xsl:if test="$null=0">
+	    <xsl:text> NOT NULL</xsl:text>
+	</xsl:if>
+
+	<xsl:choose>
+	    <xsl:when test="db:default">
+		<xsl:text> DEFAULT </xsl:text>
+		<xsl:choose>
+		    <xsl:when test="db:default/null">
+			<xsl:text>NULL</xsl:text>
+		    </xsl:when>
+		    <xsl:otherwise>
+			<xsl:text>'</xsl:text>
+			<xsl:value-of select="db:default"/>
+			<xsl:text>'</xsl:text>
+		    </xsl:otherwise>
+		</xsl:choose>
+	    </xsl:when>
+	    <xsl:when test="default">
+		<xsl:text> DEFAULT </xsl:text>
+		<xsl:choose>
+		    <xsl:when test="default/null">
+			<xsl:text>NULL</xsl:text>
+		    </xsl:when>
+		    <xsl:otherwise>
+			<xsl:text>'</xsl:text>
+			<xsl:value-of select="default"/>
+			<xsl:text>'</xsl:text>
+		    </xsl:otherwise>
+		</xsl:choose>
+	    </xsl:when>
+	</xsl:choose>
+
+	<xsl:if test="not(position()=last())">
+	    <xsl:text>,</xsl:text>
+	    <xsl:text>&#x0A;</xsl:text>
+	</xsl:if>
+    </xsl:template>
+
+    <xsl:template name="column.type">
+	<xsl:call-template name="get-type"/>
+    </xsl:template>
+
+    <xsl:template name="column.size">
+	<xsl:variable name="size">
+	    <xsl:call-template name="get-size"/>
+	</xsl:variable>
+
+	<xsl:if test="not($size='')">
+	    <xsl:text>(</xsl:text>
+	    <xsl:value-of select="$size"/>
+	    <xsl:text>)</xsl:text>
+	</xsl:if>
+    </xsl:template>
+
+    <xsl:template name="column.sign"/>
+
+<!-- ################ /COLUMN ################  -->
+
+<!-- ################ INDEX ################  -->
+
+    <xsl:template match="index">
+	<!-- Translate unique indexes into SQL92 unique constraints -->
+	<xsl:if test="unique">
+	    <xsl:if test="position()=1">
+		<xsl:text>,&#x0A;</xsl:text>
+	    </xsl:if>
+	    <xsl:text>    </xsl:text>
+
+	    <xsl:call-template name="get-name"/>
+	    <xsl:text> UNIQUE (</xsl:text>
+
+	    <xsl:apply-templates match="colref"/>
+
+	    <xsl:text>)</xsl:text>
+
+	    <xsl:if test="not(position()=last())">
+		<xsl:text>,</xsl:text>
+		<xsl:text>&#x0A;</xsl:text>
+	    </xsl:if>
+	</xsl:if>
+    </xsl:template>
+
+<!-- ################ /INDEX ################  -->
+
+<!-- ################ COLREF ################  -->
+
+    <xsl:template match="colref">
+	<xsl:variable name="columns" select="key('column_id', @linkend)"/>
+	<xsl:variable name="column" select="$columns[1]"/>
+	<xsl:choose>
+	    <xsl:when test="count($column) = 0">
+		<xsl:message terminate="yes">
+		    <xsl:text>ERROR: Column with id '</xsl:text>
+		    <xsl:value-of select="@linkend"/>
+		    <xsl:text>' does not exist.</xsl:text>
+		</xsl:message>
+	    </xsl:when>
+	    <xsl:otherwise>
+		<xsl:call-template name="get-name">
+		    <xsl:with-param name="select" select="$column"/>
+		</xsl:call-template>
+	    </xsl:otherwise>
+	</xsl:choose>
+	<xsl:if test="not(position()=last())">
+	    <xsl:text>, </xsl:text>
+	</xsl:if>
+    </xsl:template>
+
+<!-- ################ /COLREF ################  -->
+
+<!-- ################ ROW ################  -->
+
+    <xsl:template match="row">
+	<xsl:text>INSERT INTO </xsl:text>
+	<xsl:call-template name="get-name">
+	    <xsl:with-param name="select" select="parent::table"/>
+	</xsl:call-template>
+	<xsl:text> (</xsl:text>
+	<xsl:apply-templates select="value" mode="colname"/>
+	<xsl:text>) VALUES (</xsl:text>
+	<xsl:apply-imports/>
+	<xsl:text>);&#x0A;</xsl:text>
+	<xsl:if test="position()=last()">
+	    <xsl:text>&#x0A;</xsl:text>	    
+	</xsl:if>
+    </xsl:template>
+
+<!-- ################ /ROW ################  -->
+
+<!-- ################ VALUE ################  -->
+
+    <xsl:template match="value">
+	<xsl:choose>
+	    <xsl:when test="null">
+		<xsl:text>NULL</xsl:text>
+	    </xsl:when>
+	    <xsl:otherwise>
+		<xsl:text>'</xsl:text>
+		<xsl:value-of select="text()"/>
+		<xsl:text>'</xsl:text>
+	    </xsl:otherwise>
+	</xsl:choose>
+	<xsl:if test="not(position()=last())">
+	    <xsl:text>, </xsl:text>
+	</xsl:if>
+    </xsl:template>
+
+    <xsl:template match="value" mode="colname">
+	<xsl:variable name="columns" select="key('column_id', @col)"/>
+	<xsl:variable name="column" select="$columns[1]"/>
+	<xsl:choose>
+	    <xsl:when test="count($column) = 0">
+		<xsl:message terminate="yes">
+		    <xsl:text>ERROR: Column with id '</xsl:text>
+		    <xsl:value-of select="@col"/>
+		    <xsl:text>' does not exist.</xsl:text>
+		</xsl:message>
+	    </xsl:when>
+	    <xsl:otherwise>
+		<xsl:call-template name="get-name">
+		    <xsl:with-param name="select" select="$column"/>
+		</xsl:call-template>
+	    </xsl:otherwise>
+	</xsl:choose>
+	<xsl:if test="not(position()=last())">
+	    <xsl:text>, </xsl:text>
+	</xsl:if>
+    </xsl:template>
+
+<!-- ################ /VALUE ################  -->
+
+</xsl:stylesheet>