<!-- $Id: grammar.xsl,v 1.3 2002/05/22 13:30:07 jjc Exp $ -->
<!DOCTYPE xsl:stylesheet [
<!ENTITY nbsp "&#160;">
]>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:rng="http://relaxng.org/ns/structure/1.0"
                xmlns:fo="http://www.w3.org/1999/XSL/Format"
                exclude-result-prefixes="rng">

<xsl:variable name="grammar-font" select="'Arial'"/>

<xsl:variable name="rng:conn-none" select="0"/>
<xsl:variable name="rng:conn-or" select="1"/>
<xsl:variable name="rng:conn-seq" select="2"/>
<xsl:variable name="rng:conn-top" select="3"/>

<xsl:template match="rng:grammar">
  <fo:block xsl:use-attribute-sets="para" text-align="left" linefeed-treatment="preserve">
    <xsl:apply-templates select="rng:define"/>
  </fo:block>
</xsl:template>

<xsl:template match="rng:define">
  <xsl:value-of select="@name"/>
  <xsl:text>&nbsp;&nbsp;::=&nbsp;&nbsp;</xsl:text>
  <xsl:call-template name="line-break"/>
  <xsl:text>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</xsl:text>
    <xsl:call-template name="rng:pattern">
      <xsl:with-param name="conn-cur" select="$rng:conn-top"/>
      <xsl:with-param name="sub" select="*"/>
    </xsl:call-template>
  <xsl:call-template name="line-break"/>
</xsl:template>

<xsl:template match="rng:choice">
  <xsl:param name="conn-cur" select="$rng:conn-none"/>
  <xsl:param name="conn-new" select="$rng:conn-seq"/>
  <xsl:call-template name="rng:pattern">
    <xsl:with-param name="conn-new" select="$rng:conn-or"/>
    <xsl:with-param name="conn-cur" select="$conn-cur"/>
    <xsl:with-param name="sub" select="*"/>
  </xsl:call-template>
</xsl:template>

<xsl:template match="rng:zeroOrMore">
  <xsl:call-template name="rng:pattern">
    <xsl:with-param name="sub" select="*"/>
  </xsl:call-template>
  <xsl:text>*</xsl:text>
</xsl:template>

<xsl:template match="rng:oneOrMore">
  <xsl:call-template name="rng:pattern">
    <xsl:with-param name="sub" select="*"/>
  </xsl:call-template>
  <xsl:text>+</xsl:text>
</xsl:template>

<xsl:template match="rng:optional">
  <xsl:text>[</xsl:text>
  <xsl:call-template name="rng:pattern">
    <xsl:with-param name="sub" select="*"/>
    <xsl:with-param name="conn-cur" select="$rng:conn-top"/>
  </xsl:call-template>
  <xsl:text>]</xsl:text>
</xsl:template>

<xsl:template match="rng:group">
  <xsl:param name="conn-cur" select="$rng:conn-none"/>
  <xsl:param name="conn-new" select="$rng:conn-seq"/>
  <xsl:call-template name="rng:pattern">
    <xsl:with-param name="conn-new" select="$rng:conn-seq"/>
    <xsl:with-param name="conn-cur" select="$conn-cur"/>
    <xsl:with-param name="sub" select="*"/>
  </xsl:call-template>
</xsl:template>

<xsl:template match="rng:ref">
  <fo:wrapper font-style="italic"><xsl:value-of select="@name"/></fo:wrapper>
</xsl:template>

<xsl:template match="rng:element">
  <xsl:param name="conn-cur" select="$rng:conn-none"/>
  <xsl:param name="conn-new" select="$rng:conn-seq"/>
  <fo:wrapper font-family="{$grammar-font}">&lt;<xsl:value-of select="@name"/></fo:wrapper>
  <xsl:for-each select="rng:attribute|rng:optional[rng:attribute]">
    <xsl:text> </xsl:text>
    <xsl:apply-templates select="."/>
  </xsl:for-each>
  <xsl:variable name="children"
    select="*[not(self::rng:attribute|self::rng:optional[rng:attribute])]"/>
  <xsl:choose>
    <xsl:when test="
 not($children) or ($children[self::rng:empty] and count($children) = 1)">
     <fo:wrapper font-family="{$grammar-font}">/&gt;</fo:wrapper>
    </xsl:when>
    <xsl:otherwise>
      <fo:wrapper font-family="{$grammar-font}">&gt; </fo:wrapper>
      <xsl:call-template name="rng:pattern">
        <xsl:with-param name="conn-new" select="$rng:conn-seq"/>
        <xsl:with-param name="conn-cur" select="$rng:conn-seq"/>
	<xsl:with-param name="sub" select="$children"/>
      </xsl:call-template>
      <fo:wrapper font-family="{$grammar-font}"> &lt;/<xsl:value-of select="@name"/>&gt;</fo:wrapper>
    </xsl:otherwise>
  </xsl:choose>  
</xsl:template>

<xsl:template match="rng:attribute">
  <fo:wrapper font-family="{$grammar-font}"><xsl:value-of select="@name"/>="</fo:wrapper>
  <xsl:call-template name="rng:pattern">
    <xsl:with-param name="sub" select="*"/>
    <xsl:with-param name="conn-cur" select="$rng:conn-top"/>
  </xsl:call-template>
  <fo:wrapper font-family="{$grammar-font}">"</fo:wrapper>
</xsl:template>

<xsl:template match="rng:value">
  <fo:wrapper font-family="{$grammar-font}"><xsl:value-of select="."/></fo:wrapper>
</xsl:template>

<xsl:template name="rng:pattern">
  <xsl:param name="conn-cur" select="$rng:conn-none"/>
  <xsl:param name="conn-new" select="$rng:conn-seq"/>
  <xsl:param name="sub" select="/.."/>
  <xsl:choose>
    <xsl:when test="count($sub)>1
                    and $conn-new != $conn-cur
                    and $conn-cur != $rng:conn-top">
      <xsl:text>(</xsl:text>
      <xsl:call-template name="rng:pattern">
        <xsl:with-param name="conn-new" select="$conn-new"/>
        <xsl:with-param name="conn-cur" select="$conn-new"/>
        <xsl:with-param name="sub" select="$sub"/>
      </xsl:call-template>
      <xsl:text>)</xsl:text>
    </xsl:when>
    <xsl:when test="count($sub)>1">
      <xsl:for-each select="$sub">
        <xsl:if test="position() != 1">
          <xsl:choose>
            <xsl:when test="$conn-new=$rng:conn-seq"><xsl:text> </xsl:text></xsl:when>
            <xsl:when test="parent::*/parent::rng:define[count(*)=1]"><xsl:call-template name="line-break"/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| </xsl:when>
            <xsl:otherwise> | </xsl:otherwise>
          </xsl:choose> 
        </xsl:if>
        <xsl:apply-templates select=".">
          <xsl:with-param name="conn-new" select="$conn-new"/>
          <xsl:with-param name="conn-cur" select="$conn-new"/>
        </xsl:apply-templates>
      </xsl:for-each>
    </xsl:when>
    <xsl:otherwise>
      <xsl:apply-templates select="$sub">
        <xsl:with-param name="conn-new" select="$conn-new"/>
        <xsl:with-param name="conn-cur" select="$conn-cur"/>
      </xsl:apply-templates>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template match="rng:data">
  <fo:wrapper font-style="italic"><xsl:value-of select="@type"/></fo:wrapper>
</xsl:template>

<xsl:template name="line-break">
  <xsl:text>&#xA;</xsl:text>
</xsl:template>

</xsl:stylesheet>
