Search code examples
xmlxslttei

XSLT – transforming definition lists (TEI)


I can’t figure out a very simple thing!

I am trying to write a template for transforming definition lists.

<list type="gloss">
  <head>Slovníček pojmů</head>
  <label xml:lang="cs">Pojem</label>
  <item>Dojem!</item>
  <label xml:lang="cs">Stavba</label>
  <item>Stavení</item>
</list>

current template:

<xsl:template match="tei:list[@type='gloss']">
    <div class="glossary">
        <p>
            <b>
                <xsl:apply-templates select="tei:head"/>
            </b>
        </p>
        <dl>
            <xsl:choose>
                <xsl:when test="tei:label">
                    <dt>
                        <xsl:apply-templates select="tei:label"/>
                    </dt>
                </xsl:when>
                <xsl:otherwise>
                    <dd>
                        <xsl:apply-templates select="tei:item"/>
                    </dd>
                </xsl:otherwise>
            </xsl:choose>
        </dl>
    </div>
</xsl:template>

Nothing works. I have tried for-each looping, which makes problems because of applying templates to an atomic values. External templates (outside of this one) usually render the head tag in a wrong way (twice). Is there any simple way how to do this?

The template above throws error mentioning there are too many nested calls for templates (the stylesheet may be looping).


Solution

  • This should work with the snippet you have posted:

    <xsl:template match="list[@type='gloss']">
        <div class="glossary">
            <p>
                <b>
                    <xsl:value-of select="head"/>
                </b>
            </p>
            <dl>
                <xsl:for-each select="label">
                    <dt>
                        <xsl:value-of select="."/>
                    </dt>
                    <dd>
                        <xsl:value-of select="following-sibling::item[1]"/>
                    </dd>
                </xsl:for-each>
            </dl>
        </div>
    </xsl:template>
    

    Or, if you prefer:

    <xsl:template match="list[@type='gloss']">
        <div class="glossary">
            <xsl:apply-templates select="head"/>
            <dl>
                <xsl:apply-templates select="label | item"/>
            </dl>
        </div>
    </xsl:template>
    
    <xsl:template match="head">
        <p>
            <b>
                <xsl:value-of select="."/>
            </b>
        </p>
    </xsl:template>
    
    <xsl:template match="label">
        <dt>
            <xsl:value-of select="."/>
        </dt>
    </xsl:template>
    
    <xsl:template match="item">
        <dd>
            <xsl:value-of select="."/>
        </dd>
    </xsl:template>
    

    Result

    <div class="glossary">
      <p>
        <b>Slovníček pojmů</b>
      </p>
      <dl>
        <dt>Pojem</dt>
        <dd>Dojem!</dd>
        <dt>Stavba</dt>
        <dd>Stavení</dd>
      </dl>
    </div>