Lee Kelleher’s Weblog

random posts on code, .NET, Umbraco and WordPress

How to use umbraco.library GetMedia in XSLT

with 12 comments

From time to time I notice a reoccurring post over at the Our Umbraco forum; how to display an image (from the Media section) in XSLT?

A quick answer can be found on the Our Umbraco wiki for the umbraco.library GetMedia method.

For most uses, the last example in the wiki works great.  But I want to show you a “super safe” way of dealing with GetMedia in XSLT.

Where I find a lot of the examples go wrong is that they make the assumption that a media node (XML) is returned from the GetMedia call, e.g.

<xsl:value-of select="umbraco.library:GetMedia($currentPage/data[@alias='mediaId'], 'false')/data[@alias='umbracoFile']" />

If the ‘mediaId’ property didn’t contain either a numeric value or a valid media node id, then it would return null … meaning that the following “/data” would throw an Exception! (Displaying “Error parsing XSLT file” message on the front-end.)  Not what you or your users want to see!

In order to consider any user inputs, like media IDs not being selected, or even a referenced media node is deleted in the back-office, here is the “super safe” approach:

<xsl:template match="/">
	<xsl:variable name="mediaId" select="number($currentPage/data[@alias='mediaId'])" />
	<xsl:if test="$mediaId &gt; 0">
		<xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, 0)" />
		<xsl:if test="count($mediaNode/data) &gt; 0">
			<xsl:if test="string($mediaNode/data[@alias='umbracoFile']) != ''">
				<img src="{$mediaNode/data[@alias='umbracoFile']}" alt="[image]">
					<xsl:if test="string($mediaNode/data[@alias='umbracoHeight']) != ''">
						<xsl:attribute name="height">
							<xsl:value-of select="$mediaNode/data[@alias='umbracoHeight']" />
						</xsl:attribute>
					</xsl:if>
					<xsl:if test="string($mediaNode/data[@alias='umbracoWidth']) != ''">
						<xsl:attribute name="width">
							<xsl:value-of select="$mediaNode/data[@alias='umbracoWidth']" />
						</xsl:attribute>
					</xsl:if>
				</img>
			</xsl:if>
		</xsl:if>
	</xsl:if>
</xsl:template>

Here’s what happens:

  1. The “mediaId” is pulled from a property of the “currentPage” and cast as a number.  Optionally the “mediaId” could be passed in via a macro parameter, or somewhere else?
  2. The first condition checks the the “mediaId” is numeric, and greater-than zero.
  3. The “mediaId” is passed through to “GetMedia”, along with the false flag to only pull-back the required node (not it’s children, for Folder media items).
  4. We check if the media node has any child “data” elements – which contain the data about the image/media.
  5. Then we check if the “umbracoFile” property has any data – if not, then there is no point displaying an image.
  6. There are extra conditions for the “height” and “width” properties – these are optional.

Personally, I add an “altText” property to the Image media-type … and use that in the XSLT – again this is optional, but strongly recommended!

I can see how this “super safe” approach is overkill – especially compared with a single line of XSLT … but from my experience, it’s better to be safe than sorry – especially when dealing with user data-input – your assumptions and expectations of how users will use the system aren’t always correct!

Update: OK, I agree the extra “if” statements are overkill… so here’s a condensed version – assuming that the “umbracoHeight” and “umbracoWidth” properties are always there…

<xsl:template match="/">
	<xsl:variable name="mediaId" select="number($currentPage/data[@alias='mediaId'])" />
	<xsl:if test="$mediaId &gt; 0">
		<xsl:variable name="mediaNode" select="umbraco.library:GetMedia($mediaId, 0)" />
		<xsl:if test="count($mediaNode/data) &gt; 0 and string($mediaNode/data[@alias='umbracoFile']) != ''">
			<img src="{$mediaNode/data[@alias='umbracoFile']}" alt="[image]" height="{$mediaNode/data[@alias='umbracoHeight']}" width="{$mediaNode/data[@alias='umbracoWidth']}" />
		</xsl:if>
	</xsl:if>
</xsl:template> 

Written by Lee Kelleher

November 30, 2009 at 2:33 pm

Posted in blog

Tagged with , , , ,

12 Responses

Subscribe to comments with RSS.

  1. This is definitely one of the methods that I would like to get simplified. I would like to just pass an id and some parameters. Something like this:

    umbraco.library:Image(data[@alias='myphoto']) returns

    umbraco.library:Image(data[@alias='myphoto'],’@src’) returns /path/image.gif”

    Jukka-Pekka Keisala

    December 28, 2009 at 12:05 pm

    • I see the form stripped out image tag. I wanted to show you that Image(data[@alias='myphoto']) should return full image tag and when using second parameter then you can access img attributes as shown in Image(data[@alias='myphoto','@src'])

      Jukka-Pekka Keisala

      December 28, 2009 at 12:08 pm

  2. Thanks Lee,

    This was a really helpfull post!

    Nico Lubbers

    February 14, 2010 at 12:55 am

  3. Hi Lee

    Just starting out with Umbraco and have found your article invaluable.

    I was wondering if it’s possible to create a xlst/macro where the editor can also manually enter the alt text. I was hoping that this could be achieved with the Textstring datatype?

    Any advice or pointers would be greatly appreciated.

    Thanks in advance.

    Eddie

    Eddie Foreman

    April 18, 2010 at 11:06 am

    • Hi Eddie,

      My advice would be to modify the Image media-type to add a new textstring field called “altText” (or similar), then it is associated with that media item.

      If you want to have an adhoc alternative text for each media-item (in the richtext-editor), then you could add a new ‘text’ parameter to your Macro and use that in the XSLT.

      If you need further help, please post a message on the Our Umbraco forums… we’re always happy to help over there!

      http://our.umbraco.org/

      Cheers, Lee.

      Lee Kelleher

      April 19, 2010 at 10:59 pm

  4. Hey Lee,

    Good stuff! How will this change with the new v4.1 xml format? Or are media items unaffected by this?

    Cheers,

    David

    David Conlisk

    May 21, 2010 at 9:10 am

    • Hi David,

      I haven’t heard anything about the XML schema for GetMedia in v4.1 but my guess would be that it would follow the content schema, with docType and property aliases as the tag names. Might be worth keeping an eye on the CodePlex commits for v4.1? ;-)

      Cheers, Lee.

      Lee Kelleher

      May 22, 2010 at 3:06 pm

  5. Hey Lee,

    An update to the new schema would be mega-handy – still use this snippet reference loads, but working much more with 4.5 schema now.

    Cheers

    Dan

    August 11, 2010 at 3:11 pm

  6. [...] a comment » This is a quick follow-up on my previous blog post: “How to use umbraco.library GetMedia in XSLT“.  At the request of fellow Umbraco South-West UK developer, Dan, that I should update the [...]

  7. Absolutely brilliant, thank you for sharing this, very handy at 10 minutes to five :)

    John Scott

    August 24, 2010 at 4:00 pm


Leave a Reply