Search code examples
xsltxslt-2.0tei

XSLT 2.0 separating two recursive outputs


XSLT fiddle here: https://xsltfiddle.liberty-development.net/bdxtqU/5

This question follows on from the implications of this answer where I wanted to output, using XSLT 2.0, <persName> into an HTML URL, where <persName> can be found inside another <persName>, so all are turned into URLs.

<persName nymRef="#Raimunda_Faure">Raimunda uxor 
   <persName nymRef="#Bernard_Faure_Senior">Bernardi Fabri 
                   senior</persName></persName>

Outputs to:

 <a href="www.foo.com/person/Raimunda_Faure">Raimunda 
    uxor</a><a href="www.foo.com/person/Bernard_Faure_Senior">Bernardi 
      Fabri<a>

Using the code found below. And I also use it for another 'named entity' that gets output to a URL, <placeName>.

The problem is that <persName> can appear inside <placeName> like so (and vice versa):

<placeName type="event_loc" nymRef="#home_of_Guilhem_Vidal">in domo 
    <persName nymRef="#Guilhem_Vidal_MSP-AU" role="own">Willelmi Vitalis</persName></placeName>

What I'd like is a separation of <placeName> and <persName>, such that they only create nested URLs where the same named entity type is nested inside a named entity.

Schematically, these would recursively output all <placeName> and <persName>:

 <persName>text
   <persName>text</persname>
   <persName>text</persname>
 </persName>

 <placeName>text
   <placeName>text</placename>
   <placeName>text</placename>
 </placeName>

But these would only output the parent entity as URL, whether <placeName> or <persName>, and bypass the named entities contained within them:

 <persName nymRef="#Raimunda_Faure">Raimunda
   <placeName nymRef="#Toulouse">Toulouse</placename>
   <placeName nymRef="Paris">Paris</placename>
 </persName>

Output to <a href="www.foo.com/person/Raimunda_Faure">Raimunda Toulouse Paris</a>

 <placeName nymRef="#Toulouse">Toulouse
   <persName nymRef="#Raimunda_Faure">Raimunda</persname>
   <persName nymRef="#Bernard_Faure">Bernard</persname>
 </placeName>

Output to <a href="www.foo.com/place/Toulosue">Toulouse Raimunda Bernard</a>

Here are the two existing templates:

<xsl:template match="tei:text//tei:persName">
    <xsl:variable name="nested" select="tei:persName[1]|
                     tei:persName[1]/following-sibling::node()" />
    <xsl:element name="a"> 
        <xsl:attribute name="href"><xsl:value-of select="concat($paramPersonurl,substring-after(@nymRef,'#'))"/></xsl:attribute>
        <xsl:apply-templates select="node() except $nested" />
    </xsl:element>
    <xsl:apply-templates select="$nested" />
</xsl:template>

<xsl:template match="tei:text//tei:placeName">
    <xsl:variable name="nested" select="tei:placeName[1]|
                    tei:placeName[1]/following-sibling::node()" />
    <xsl:element name="a"> 
        <xsl:attribute name="href"><xsl:value-of select="concat($paramPersonurl,substring-after(@nymRef,'#'))"/></xsl:attribute>
        <xsl:apply-templates select="node() except $nested" />
    </xsl:element>
    <xsl:apply-templates select="$nested" />
</xsl:template>

It seems I should add an exclusion of the other named entity to either <xsl:apply-templates select="node() except $nested" /> or <xsl:apply-templates select="$nested" /> using something like [node()[name() != 'persName']]but I've not had success.

Thanks in advance.


Solution

  • Add a template

    <xsl:template match="tei:persName/tei:placeName | tei:placeName/tei:persName">
        <xsl:apply-templates/>
    </xsl:template>
    

    https://xsltfiddle.liberty-development.net/bdxtqU/7