Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In XSL: How to avoid choose-blocks for wrapping elements?

Tags:

xml

xslt

there is a case, that appears often times. I am parsing an XML and generate my XHTML document via XSLT 1.0.

Case:

/* XML */
<Image src="path-to-img.jpg" href="link-to-page.html" />

/* XSL */
<xsl:choose>
    <xsl:when test="@href">
    <a href="{@href}">
       <img src="{@src}"/>
    </a>
</xsl:when>
<xsl:otherwise>
    <img src="{@src}"/>
</xsl:otherwise>
</xsl:choose>

You see the problem: I am just fetching the case if there is a href set. I'm not satisfied with this approach, but I don't see another option for implementing this.

Any ideas?

like image 652
ChrisBenyamin Avatar asked Aug 26 '11 07:08

ChrisBenyamin


1 Answers

The way to eliminate explicit conditional instructions inside a template is to use pattern-matching within the match pattern of a template:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="Image[@href]">
    <a href="{@href}">
     <xsl:call-template name="basicImage" />
    </a>
 </xsl:template>

 <xsl:template match="Image" name="basicImage">
   <img src="{@src}"/>
 </xsl:template>
</xsl:stylesheet>

XSLT 2.0: There is an especially ellegant solution using <xsl:next-match>:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="Image[@href]">
    <a href="{@href}">
    <xsl:next-match/>
    </a>
 </xsl:template>

 <xsl:template match="Image" name="basicImage">
   <img src="{@src}"/>
 </xsl:template>
</xsl:stylesheet>

Both transformations, when applied on the provided XML document:

<Image src="path-to-img.jpg" href="link-to-page.html" />

produce the wanted, correct result:

<a href="link-to-page.html">
   <img src="path-to-img.jpg"/>
</a>
like image 69
Dimitre Novatchev Avatar answered Sep 28 '22 16:09

Dimitre Novatchev