Search code examples
xslttei

How to check whether one child exists in XML


I have an xslt-script that transforms a tei:bibl Element to HTML

<xsl:template match="tei:bibl//tei:author">
    <span class="smallcaps">
        <xsl:apply-templates select="tei:surname"/>
    </span>
    <xsl:text>, </xsl:text>
    <xsl:apply-templates select="tei:forename"/>
    <xsl:if test="tei:nameLink">
        <xsl:text> </xsl:text>
        <xsl:apply-templates select="tei:nameLink"/>
    </xsl:if>
    <xsl:apply-templates select="text()"/>
    <xsl:text>, </xsl:text>
    <xsl:if test=".[following-sibling::tei:author]">
    <xsl:text> / </xsl:text> 
        <span class="smallcaps">
            <xsl:text> </xsl:text>
            <xsl:apply-templates select="tei:surname"/>
        </span>
        <xsl:text>, </xsl:text>
        <xsl:apply-templates select="tei:forename"/>
        <xsl:if test="tei:nameLink">
            <xsl:text> </xsl:text>
            <xsl:apply-templates select="tei:nameLink"/>
        </xsl:if>
        <xsl:text> , </xsl:text>
    </xsl:if>
</xsl:template>

The XML looks like this:

        <bibl xml:id="capitani_ua_bannerherr">
            <abbr>
                <surname type="author">Capitani</surname> u.a., Bannerherr</abbr>
            <author>
                <forename>François</forename>
                <nameLink>de</nameLink>
                <surname>Capitani</surname>
            </author>
            <author>
                <surname>Weck</surname>
                <forename>Hervé</forename>
                <nameLink>de</nameLink>
            </author>
            <title>Bannerherr [Venner]</title>
            <bibl>
                <title>Historisches Lexikon der Schweiz (HLS)</title>
                <date>Version vom 07.05.2009</date>
            </bibl>
            <ref target="http://www.hls-dhs-dss.ch/textes/d/D8612.php" type="ex">[Online]</ref>
        </bibl>

My HTML is like this:

<span id="capitani_ua_bannerherr" class="rs-ref">
    <span class="smallcaps">Capitani</span>, François de,  / 
    <span class="smallcaps"> Capitani</span>, François de , 
    <span class="smallcaps">Weck</span>, Hervé de, Bannerherr [Venner], in: Historisches Lexikon der Schweiz (HLS), Version vom 07.05.2009<a href="http://www.hls-dhs-dss.ch/textes/d/D8612.php"> [Online]
</a>.
</span>

The template does as it is supposed to. However, It doubles the first entry (here <span class="smallcaps"> Vapitani </span>, Francois de, )

I have tried adding an <xsl:choose> that looks like this:

<xsl:template match="tei:bibl//tei:author">
        <xsl:choose>
            <xsl:when test="[count(tei:bibl//tei:author)=1]">
                <span class="smallcaps">
                    <xsl:apply-templates select="tei:surname"/>
                </span>
                <xsl:text>, </xsl:text>
                <xsl:apply-templates select="tei:forename"/>
                    <xsl:if test="tei:nameLink">
                        <xsl:text> </xsl:text>
                        <xsl:apply-templates select="tei:nameLink"/>
                    </xsl:if>
                <xsl:apply-templates select="text()"/>
                <xsl:text>, </xsl:text>
            </xsl:when>
            <xsl:when test=".[following-sibling::tei:author]">
        <xsl:text> / </xsl:text>
            <span class="smallcaps">
                <xsl:text> </xsl:text>
                <xsl:apply-templates select="tei:surname"/>
            </span>
            <xsl:text>, </xsl:text>
            <xsl:apply-templates select="tei:forename"/>
            <xsl:if test="tei:nameLink">
                <xsl:text> </xsl:text>
                <xsl:apply-templates select="tei:nameLink"/>
            </xsl:if>
            <xsl:text> , </xsl:text>
        </xsl:when>
        </xsl:choose>

</xsl:template>

This should produce output like this:

<span id="capitani_ua_bannerherr" class="rs-ref">
        <span class="smallcaps">Capitani</span>, François de,  / 
        <span class="smallcaps">Weck</span>, Hervé de, Bannerherr [Venner], in: Historisches Lexikon der Schweiz (HLS), Version vom 07.05.2009<a href="http://www.hls-dhs-dss.ch/textes/d/D8612.php"> [Online]
    </a>.
</span>

What am I doing wrong? I am not looking for any specific version of XSLT, we can use XSLT 1 -3.

all the best, K


Solution

  • Your current template says "if there is a following author, output the surname and forename". It does not say "output the surname and forename of the following author".

    I'm not 100% sure, but you seem to want the following:

    • a list of authors per <tei:bib>
    • 2nd author separated from the first with /
    • any further author separated with ,

    Let's write that down exactly like that:

    <xsl:template match="tei:bibl//tei:author">
        <xsl:if test="position() = 2"> / </xsl:if>
        <xsl:if test="position() &gt; 2"> , </xsl:if>
        <span class="smallcaps">
            <xsl:apply-templates select="tei:surname" />
        </span>
        <xsl:text>, </xsl:text>
        <xsl:apply-templates select="tei:forename" />
        <xsl:if test="tei:nameLink">
            <xsl:text> </xsl:text>
            <xsl:apply-templates select="tei:nameLink" />
        </xsl:if>
    </xsl:template>
    

    Now you can invoke that in a straight-forward manner

    <xsl:template match="tei:bibl">
        <xsl:apply-templates select="tei:author" />
        <!-- ...output the title etc here --->
    </xsl:template>
    

    and get (formatted for readability):

    <span xmlns:tei="tei" class="smallcaps">Capitani</span>, François de
    / <span xmlns:tei="tei" class="smallcaps">Weck</span>, Hervé de