My stylesheet used version="3.0"
. My engine version Saxon PEE 9.9.1.7.
The xml:id
attribute of w
is built from xml:id
of l
+ '_'
+ the text()
value of w
. It seems to me that the xpath
of xml:id
of l
is correct, but this doesn't work.
Example of xml
before transformation:
<div3 xml:id="ktu1-1_ii">
<!-- tei elements div4 and lg -->
<l n="1a">
<!-- other children -->
<w>l</w>
</l>
Processing instructions:
<xsl:template match="div3/div4/lg/l">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:if test="not(@xml:id)">
<xsl:attribute name="xml:id">
<xsl:value-of select="concat(ancestor::div3/@xml:id, '_l', @n)"/>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="l/w">
<xsl:variable name="xmlid">
<xsl:value-of select="ancestor::l/@xml:id"/>
</xsl:variable>
<xsl:message select="$xmlid"/> <!-- test @xml:id, nothing -->
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="pos"></xsl:attribute>
<!-- Calculate xml:id based on parent 'l' xml:id -->
<xsl:attribute name="xml:id">
<xsl:value-of select="normalize-space(replace(ancestor::l/@xml:id, ' ', '')) || '_' || replace(., '\s|̊', '')"/>
</xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
The result is correct for l
: <l n='1a' xml:id='ktu1-1_ii_l1a'>
, but only one part works for w
<w xml:id="_l">l</w>
when the result should be <w xml:id="ktu1-1_ii_l1a_l">l</w>
.
Any idea where the error might have come from?
Consider the following (simplified) example:
XML
<div3 xml:id="ktu1-1_ii">
<!-- tei elements div4 and lg -->
<l n="1a">
<!-- other children -->
<w>l</w>
<w>l</w>
</l>
</div3>
XSLT 3.0
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="l[not(@xml:id)]">
<xsl:variable name="l_id" select="concat(ancestor::div3/@xml:id, '_l', @n)"/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="xml:id" select="$l_id"/>
<xsl:apply-templates>
<xsl:with-param name="l_id" select="$l_id"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="w">
<xsl:param name="l_id"/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="xml:id" select="concat($l_id, '_', position())"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<div3 xml:id="ktu1-1_ii"><!-- tei elements div4 and lg -->
<l n="1a" xml:id="ktu1-1_ii_l1a"><!-- other children -->
<w xml:id="ktu1-1_ii_l1a_2">l</w>
<w xml:id="ktu1-1_ii_l1a_3">l</w>
</l>
</div3>
Here the value of the l
parent's xml:id
is calculated once and passed down to the children as a parameter.
P.S. The purpose of this exercise is not entirely clear. If you need to have a unique ID for each node, you could simply have your stylesheet generate them instead of trying to assemble them piecemeal from their ancestor parts.