I have separated certain statements to be applied on a specific element in a separate template.
The element is processed in one template, which contains a statement <xsl:apply-templates/>.
Is there a way to have an element just processed in the first template, to be re-processed in the second (non-named) template?
Of course I know that I could use a named template and call that from the first template, but I am just wondering whether it could be done like this.
To give you something to work with, here’s a heavily simplified model of the stuff I am working on.
I have an html input file containing a table:
<?xml version="1.0" encoding="UTF-8"?>
<table>
<tbody>
<tr>
<td>content</td>
<td></td>
<td/>
</tr>
</tbody>
</table>
I wish to have a block element inside each td element that encloses the td string content if there is one, or is empty when the td element itself is empty. I tried the following (note again that I do not wish to do major changes in the first template!):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="*">
<xsl:copy>
<xsl:attribute name="test"><xsl:value-of select="local-name()"/></xsl:attribute>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="td/text()">
<block><xsl:value-of select="."/></block>
</xsl:template>
</xsl:stylesheet>
Where the added attribute is just a modelled example of the stuff that is being done in the first template.
which gives as output
<?xml version="1.0" encoding="UTF-8"?>
<table test="table">
<tbody test="tbody">
<tr test="tr">
<td test="td">
<block>content</block>
</td>
<td test="td"/>
<td test="td"/>
</tr>
</tbody>
</table>
and I wish to get
<?xml version="1.0" encoding="UTF-8"?>
<table test="table">
<tbody test="tbody">
<tr test="tr">
<td test="td">
<block>content</block>
</td>
<td test="td">
<block/>
</td>
<td test="td">
<block/>
</td>
</tr>
</tbody>
</table>
It is clear why it did not work: there is no text node in the empty td elements, so these are not matched by the second template’s Xpath expression.
So I started thinking about ways to re-process the td elements itself by a second template. Of course, I can not use match="td[some condition]" because then the first template will not be applied.
And I can also not use match= "self::td" because the self axis is not allowed in template match attributes (except in conditions of course), or rather, it needs a current node which you don’t have yet when starting to match.
So is there a suitable Xpath expression available for the second template that will give me what I want?
Or is there another simple way to trigger another (non-named) template for an element just processed in one template?
Note: I am not looking for simple updates on the second template, that add the attribute there. I wish the first template to add the attribute, and the second to add the block elements.
Try adding another “moded” template. You should be able to use
xsl:apply-templateswith the mode.Example xsl:template:
Example xsl:apply-templates: