Instead of two modes, use one mode and move the wide vs not-wide logic into the template match expressions:
<xsl:template match="image[meta/@width > meta/@height]">
<!-- logic for wide image -->
</xsl:template>
<xsl:template match="image">
<!-- logic for not-wide image -->
</xsl:template>
And now you can just apply templates to all the images in one go without the choose
:
<xsl:apply-templates select="$image-entry/image"/>
To ignore the caption if there's no source, I'd move the caption logic into another template matching the source
element
<xsl:template match="source" mode="caption">
<p class="full-width-caption">
Image courtesy of: <a href="{.}"><xsl:value-of select="../title"/></a>
</p>
</xsl:template>
Then in the main template do:
<xsl:apply-templates select="../source" mode="caption"/>
If there is a source this will produce a caption, if there isn't then it'll produce nothing.
Given the example you've just added to the question it looks like you want to exclude the caption no when the source
element "doesn't exist" but rather if it has no value. You can do this by changing the above apply-templates
to
<xsl:apply-templates select="../source[string()]" mode="caption" />
This would add a caption for <source handle="">something</source>
but not for <source handle="" />
.
What this is doing is filtering so we only select the ../source
element if the [string()]
predicate is true. The string()
function returns the "string value" of the context element (the source
in this case) and a string in boolean context is treated as false if it is empty and true otherwise. So in this case the effect is to apply templates to the source
element only if it has a non-empty value.