there is a case, that appears often times. I开发者_Python百科 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?
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>
To avoid duplication of code, you could make use of named templates, to contain the code for rendering the img tag
<xsl:template name="img">
<img src="{@src}" />
</xsl:template>
You can then call it like so
<xsl:call-template name="img" />
So, the finished XSLT would be
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/Image ">
<xsl:choose>
<xsl:when test="@href">
<a href="{@href}">
<xsl:call-template name="img" />
</a>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="img" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="img">
<img src="{@src}" />
</xsl:template>
</xsl:stylesheet>
Although you still have two xsl:call-template commands, any changes to the rendering of the img tag now only have to be done in one place. You could also call this template from anywhere within your XSLT, assuming the current node is an image node.
Option #1 you can create non-conditional a
and image bellow and using xsl:if
append attribute (note in this case there is some lack - always exists tag a
but without href - for end user it is not a problem):
<a>
<xsl:if test="@href">
<xsl:attribute name="href" value="{@href}"/>
</xsl:if>
<img src="{@src}"/>
</a>
Option #2 If javascript is applicable - just place to img handling of onclick
精彩评论