<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="/pool/xslt_ht.xslt" type="application/xml"?>
<xsl:stylesheet
  xmlns = "http://relaxng.org/ns/structure/1.0"
  xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
  xmlns:d = "http://herbaer.de/xmlns/20051201/doc"
  xmlns:dd = "http://herbaer.de/xmlns/20201201/dbdump"
  xmlns:xl = "http://www.w3.org/1999/xlink"
  version = "1.0"
  exclude-result-prefixes = "dd"
>
<!--
  RelaxNG-Schema aus Datenbank-Dump
  2020-12-04 Herbert Schiemann <h.schiemann@herbaer.de>
  Borkener Str. 167, 46284 Dorsten, Deutschland
  GPL Version 2 oder neuer
  Jede Gewährleistung ist ausgeschlossen.
-->
<d:info xmlns="http://herbaer.de/xmlns/20051201/doc">
  <title>dump_rng.xslt</title>
  <subtitle>RelaxNG aus Datenbank-Dump</subtitle>
  <date>2020-12-04</date>
  <author>
    <personname>
      <firstname>Herbert</firstname>
      <surname>Schiemann</surname>
    </personname>
    <email>h.schiemann@herbaer.de</email>
  </author>
</d:info>

<d:section xmlns="http://herbaer.de/xmlns/20051201/doc" role="stylesheet">
  <para>
Erzeugt aus den Angaben zur Datenbank-Struktur in einer Datenbank-Dump-Datei
eine RelaxNG - Datei, die die XML-Elemente beschreibt,
die für die Inhalte der Datenbank benutzt werden.
  </para>
  <para>
Der Name des Top-Level-Elements ist der Datenbank-Name,
die Namen der Kind-Elemente sind die Tabellennamen,
die Namen derer Kind-Elemente sind die Feldnamen.
  </para>
</d:section>

<d:para>Erstellungszeit</d:para>
<xsl:param name="p_date"/>

<d:para>Stylesheet-Anweisung in der Ausgabe</d:para>
<xsl:param name="p_xslt"/>

<xsl:output method="xml" encoding="utf-8" indent="yes"/>

<d:para>Wurzelelement</d:para>
<xsl:template match="/dd:dbdump">
  <xsl:variable name="dbname" select="dd:dbname"/>
  <xsl:variable name="ns" select="concat ('http://herbaer.de/xmlns/20201201/dbcontents/', $dbname)"
  />
  <xsl:if test="string-length ($p_xslt) &gt; 0">
    <xsl:processing-instruction name="xml-stylesheet">
      <xsl:text>href="</xsl:text>
      <xsl:value-of select="$p_xslt"/>
      <xsl:text>" type="application/xml"</xsl:text>
    </xsl:processing-instruction>
  </xsl:if>
  <grammar ns="{$ns}">
    <d:info xmlns="http://herbaer.de/xmlns/20051201/doc">
      <title>
        <xsl:text>db_</xsl:text>
        <xsl:value-of select="$dbname"/>
        <xsl:text>.rng</xsl:text>
      </title>
      <subtitle>
        <xsl:text>Inhalt der Datenbank </xsl:text>
        <xsl:value-of select="$dbname"/>
      </subtitle>
      <xsl:if test="string-length ($p_date) &gt; 0">
        <date><xsl:value-of select="$p_date"/></date>
      </xsl:if>
      <annotation>
        <para>Automatisch erzeugt</para>
      </annotation>
    </d:info>

    <start>
      <ref name="el_{$dbname}"/>
    </start>

    <define name="anything">
      <d:para>Beliebiger Inhalt</d:para>
      <zeroOrMore>
        <choice>
          <element>
            <anyName/>
            <ref name="anything"/>
          </element>
          <attribute>
            <anyName/>
          </attribute>
          <text/>
        </choice>
      </zeroOrMore>
    </define><!-- anything -->

    <define name="foreign_att">
      <d:para>Attribute anderer XML-Namensräume</d:para>
      <zeroOrMore>
        <attribute>
          <anyName>
            <except>
              <nsName ns=""/>
              <nsName ns="{$ns}"/>
            </except>
          </anyName>
        </attribute>
      </zeroOrMore>
    </define><!-- foreign_att -->

    <define name="foreign_el">
      <d:para>Elemente anderer XML-Namensräume</d:para>
      <zeroOrMore>
        <element>
          <anyName>
            <except>
              <nsName ns="{$ns}"/>
            </except>
          </anyName>
          <ref name="anything"/>
        </element>
      </zeroOrMore>
    </define><!-- foreign_el -->

    <define name="el_{$dbname}">
      <d:para>Das Wurzelelement: Inhalt der Datenbank</d:para>
      <element name="{$dbname}">
        <ref name="foreign_att"/>
        <interleave>
          <ref name="foreign_el"/>
          <xsl:apply-templates select="dd:table" mode="ref"/>
        </interleave>
      </element>
    </define>

    <!-- Datenbank-Tabellen -->
    <xsl:apply-templates select="dd:table" mode="spec"/>
  </grammar>
</xsl:template>

<d:para>
Verweise auf die Elemente, die die Tabellen spezifizieren.
</d:para>
<xsl:template match="dd:dbdump/dd:table" mode="ref">
  <zeroormore>
    <ref name="el_tbl_{dd:tabname}"/>
  </zeroormore>
</xsl:template>

<d:para>
Die Spezifikation der Tabellen
</d:para>
<xsl:template match="dd:dbdump/dd:table" mode="spec">
  <xsl:variable name="tnam" select="dd:tabname"/>
  <define name="el_tbl_{$tnam}">
    <d:para>
      <xsl:text>Tabelle </xsl:text>
      <xsl:value-of select="$tnam"/>
    </d:para>
    <element name="{$tnam}">
      <ref name="foreign_att"/>
      <interleave>
        <ref name="foreign_el"/>
        <xsl:apply-templates select="dd:field" mode="ref">
          <xsl:with-param name="tnam" select="$tnam"/>
        </xsl:apply-templates>
      </interleave>
    </element>
  </define>
  <!-- Spezifikation der Felder -->
  <xsl:apply-templates select="dd:field" mode="spec">
    <xsl:with-param name="tnam" select="$tnam"/>
  </xsl:apply-templates>
</xsl:template>

<d:para>
Verweise auf die Elemente, die die Felder einer Tabelle spezifizieren
</d:para>
<xsl:template match="dd:table/dd:field" mode="ref">
  <xsl:param name="tnam"/>
  <xsl:choose>
    <xsl:when test="dd:null">
      <optional>
        <ref name="el_fld_{$tnam}_{dd:name}"/>
      </optional>
    </xsl:when>
    <xsl:otherwise>
      <ref name="el_fld_{$tnam}_{dd:name}"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<d:para>
Die Felder einer Tabelle,
Datentypen s.
<d:uri xl:href="https://mariadb.com/kb/en/data-types/"
>https://mariadb.com/kb/en/data-types/</d:uri>
</d:para>
<xsl:template match="dd:table/dd:field" mode="spec">
  <xsl:param name="tnam"/>
  <xsl:variable name="tp" select="dd:type"/>
  <define name="el_fld_{$tnam}_{dd:name}">
    <d:para>
      <xsl:value-of select="concat ('Feld ', $tnam, '.', dd:name)"/>
      <xsl:apply-templates select="dd:type"/>
    </d:para>
    <element name="{dd:name}">
      <ref name="foreign_att"/>
      <xsl:choose>
        <xsl:when test="starts-with ($tp, 'bool')">
          <data type="boolean"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'tinyint')">
          <data type="integer"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'smallint')">
          <data type="integer"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'mediumint')">
          <data type="integer"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'int')">
          <data type="integer"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'bigint')">
          <data type="integer"/>
        </xsl:when>
        <xsl:when
          test = "
            starts-with ($tp, 'dec')
            or starts-with ($tp, 'numeric')
            or starts-with ($tp, 'fixed')
            or starts-with ($tp, 'number')
          "
        >
          <data type="decimal"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'float')">
          <data type="number"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'double')">
          <data type="number"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'bit')">
          <data type="bitfield"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'binary')">
          <data type="binary"/>
        </xsl:when>
        <!-- Datum und Zeit -->
        <xsl:when test="starts-with ($tp, 'datetime')">
          <data type="datetime"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'date')">
          <data type="date"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'timestamp')">
          <data type="datetime"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'time')">
          <data type="time"/>
        </xsl:when>
        <xsl:when test="starts-with ($tp, 'year')">
          <data type="year"/>
        </xsl:when>
        <xsl:otherwise>
          <text/>
        </xsl:otherwise>
      </xsl:choose>
    </element>
  </define>
</xsl:template>

<d:para>
Datentyp eines Feldes in der Anmerkung
</d:para>
<xsl:template match="dd:field/dd:type">
  <xsl:text>: Datentyp </xsl:text>
  <xsl:value-of select="."/>
</xsl:template>

</xsl:stylesheet>
