Unlocking the Mysteries of Data View Web Part XSL Tags – Part 20 – <xsl:import>

This entry is part 20 of 21 in the series Unlocking the Mysteries of Data View Web Part XSL Tags

Cross-posted from EndUserSharePoint.com

Whoa, Bessie! I forgot about one of the most useful XSL tags for Data View Web Parts (DVWPs)!  <xsl:import> allows you to be highly modular in storing your XSL templates for reuse.  I mentioned this back in Part 13 briefly, but I should go into it in some more detail.  This post will be sort of a twofer: I’ll explain <xsl:import> and also give you a few of the templates that I find myself storing separately from my DVWPs and reusing again and again.  (Thanks to James Love and his recent great post Sharepoint Designer – DataView Web Parts – streamlining the Newsletter Layout and follow up questions for jogging my memory.)

At the top of the XSL section of the DVWP, immediately after the <xsl:stylesheet> line (I’ve truncated it below to keep things neat and tidy.), you can add an <xsl:import> tag.  This is the *only* place in the XSL that <xsl:import> is permissible.  You can have multiple <xsl:import>s, but they need to be in this exact location.

<Xsl>
<xsl:stylesheet [snip] >
  <xsl:import href="/XSL/Utilities.xsl"/>
  <xsl:output method="html" indent="no"/>

Depending on whether I’m working with WSS or MOSS, I’ll store the common XSL in a different place. As far as I know, there’s no accepted best practice on this; as long as you are consistent you’ll be better off than most people.  In WSS, I create a Document Library at the root of the Site Collection called XSL.  In MOSS, I store the common XSL in /Style Library/XSL Style Sheets/Style Library/XSL Style Sheets is where the XSL for the Content Query Web Part (CQWP) lives, so it seems as good a place as any.

Each of the common XSL files needs to take the following form.  You can include as many templates as you want, of course.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet [snip] >
  <xsl:template name="GetUserName">
    <xsl:param name="Person"/>
      <xsl:value-of select="substring-after(substring-before(substring-after($Person, 'ID='), '&lt;'), '&gt;')"/>
  </xsl:template>
</xsl:stylesheet>

The template above called GetUserName does pretty much what it says: given a value from a Person or Group column, the template strips out the user’s name.

You must include the XML definition and the <xsl:stylesheet>; tag again, even though it is in your DVWP to start with.  I can’t really tell you why, frankly, but if you don’t, you’ll run into trouble.  Trust me on this.

This external XSL file can contain any templates that you want to use in more than one place, or just templates that you’d like to isolate from the DVWP for better management.  A few caveats: You lose some of the Intellisense, SharePoint Designer doesn’t play nicely with your formatting once you move XSL into this separate file, and parameters and variables must be defined and scoped properly. I generally build all of the XSL inside the actual DVWP and then move it out into the separate file for use elsewhere.

So what type of other things might you include in these separate XSL files which you import into DVWPs with <xsl:import>?  Well, here are a few of my commonly used utility templates, which I usually store in Utilities.XSL. (Most of these are from my blog, so they won’t be new to my regular readers.  I’m including links to the original blog posts in case you’d like more information.)

This template returns the user’s ID  from the blob of HTML which represents the user in a SharePoint Person or Group column:

<xsl:template name="GetUserID">
	<xsl:param name="Person"/>
	<xsl:value-of select=" substring-before(substring-after($Person, 'ID='), '&quot;')"/>
</xsl:template>

These two templates help to format the values in a multi-select column more nicely. The first is for use with values from a list DataSource and the second is for use with the values returned from a DataSource which uses a Web Service to retrieve list contents, usually from a different SharePoint Site Collection. Displaying a Multi-Select Column “Nicely”

<xsl:template name="MultiSelectDisplay">
  <xsl:param name="MultiSelectValue"/>
  <xsl:param name="MultiSelectSeparator"/>
  <xsl:choose>
    <xsl:when test="contains($MultiSelectValue, ';')">
      <xsl:value-of select="concat(substring-before($MultiSelectValue, ';'), $MultiSelectSeparator)" disable-output-escaping="yes"/>
      <xsl:call-template name="MultiSelectDisplay">
        <xsl:with-param name="MultiSelectValue" select="substring-after($MultiSelectValue, ';')"/>
        <xsl:with-param name="MultiSelectSeparator" select="$MultiSelectSeparator"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$MultiSelectValue" disable-output-escaping="yes"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

Displaying a Multi-Select Column “Nicely” in a DVWP with Web Services

<xsl:template name="MultiSelectDisplayWS">
  <xsl:param name="MultiSelectValue"/>
  <xsl:param name="MultiSelectSeparator"/>
  <xsl:choose>
    <xsl:when test="contains($MultiSelectValue, ';#')">
      <xsl:value-of select="concat(substring-before(substring-after($MultiSelectValue, ';#'), ';#'), $MultiSelectSeparator)" disable-output-escaping="yes"/>
      <xsl:call-template name="MultiSelectDisplayWS">
        <xsl:with-param name="MultiSelectValue" select="substring-after(substring-after($MultiSelectValue, ';#'), ';#')"/>
        <xsl:with-param name="MultiSelectSeparator" select="$MultiSelectSeparator"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="substring-after($MultiSelectValue, ';#')" disable-output-escaping="yes"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

The Alpha template lets you display an alphabetical navigational filter for values in a list. Alpha Selection of List Items in a Data View Web Part (DVWP)

<xsl:template name="Alpha">
<xsl:param name="Rows"/>
<xsl:param name="RemainingLetters"/>
<xsl:variable name="ThisLetter" select="substring($RemainingLetters, 1, 1)"/>
<td>
<xsl:attribute name="style">
<xsl:if test="$ThisLetter = $Letter">font-weight:bold;</xsl:if>
</xsl:attribute>
<xsl:choose>
<xsl:when test="count(/dsQueryResponse/Rows/Row[starts-with(@Title, $ThisLetter)])">
<a href="{$URL}?Letter={$ThisLetter}"><xsl:value-of select="$ThisLetter"/></a>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$ThisLetter"/>
</xsl:otherwise>
</xsl:choose>
</td>
<xsl:if test="string-length($RemainingLetters) &gt; 1">
<xsl:call-template name="Alpha">
<xsl:with-param name="Rows" select="$Rows"/>
<xsl:with-param name="RemainingLetters" select="substring-after($RemainingLetters, $ThisLetter)"/>
</xsl:call-template>
</xsl:if>
</xsl:template>

I built the following two templates together when I wanted to be able to display the start of blog posts without the Rich Text formatting. You can use them together or separately. Displaying the First N Words of a Long Rich Text Column with XSL

<xsl:template name="StripHTML">
  <xsl:param name="HTMLText"/>
  <xsl:choose>
   <xsl:when test="contains($HTMLText, '<')">
    <xsl:call-template name="StripHTML">
      <xsl:with-param name="HTMLText" select="concat(substring-before($HTMLText, 'LT_SIGN'),
        substring-after($HTMLText, 'GT_SIGN'))"/>
    </xsl:call-template>
   </xsl:when>
   <xsl:otherwise>
    <xsl:value-of select="$HTMLText"/>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:template>
  <xsl:template name="FirstNWords">
    <xsl:param name="TextData"/>
<xsl:param name="WordCount"/>
    <xsl:param name="MoreText"/>
    <xsl:choose>
      <xsl:when test="$WordCount > 1 and
            (string-length(substring-before($TextData, ' ')) > 0 or
            string-length(substring-before($TextData, '  ')) > 0)">
        <xsl:value-of select="concat(substring-before($TextData, ' '), ' ')" disable-output-escaping="yes"/>
        <xsl:call-template name="FirstNWords">
          <xsl:with-param name="TextData" select="substring-after($TextData, ' ')"/>
          <xsl:with-param name="WordCount" select="$WordCount - 1"/>
          <xsl:with-param name="MoreText" select="$MoreText"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="(string-length(substring-before($TextData, ' ')) > 0 or
            string-length(substring-before($TextData, '  ')) > 0)">
        <xsl:value-of select="concat(substring-before($TextData, ' '), $MoreText)" disable-output-escaping="yes"/>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$TextData" disable-output-escaping="yes"/>
      </xsl:otherwise>
  </xsl:choose>
</xsl:template>

The FixEscapedChars template was one of the first recursive templates which I wrote. (Many of these templates are recursive, and recursion is very powerful!) It helps to clean up escaped apostrophes in text values. Recursive XSL Templates in DVWPs

<xsl:template name="FixEscapedChars">
  <xsl:param name="MultiSelectValue"/>
  <xsl:variable name="Apostrophe">'</xsl:variable>
  <xsl:choose>
    <xsl:when test="contains($MultiSelectValue, '&amp;#39;')">
      <xsl:call-template name="FixEscapedChars">
        <xsl:with-param name="MultiSelectValue" select="concat(substring-before($MultiSelectValue, '&amp;#39;'), $Apostrophe, substring-after($MultiSelectValue, '&amp;#39;'))"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$MultiSelectValue"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

GetPercentileValue lets you get the value of a column which represents a given percentile in a set of values.

<xsl:template name="GetPercentileValue">
  <xsl:param name="Rows"/>
  <xsl:param name="ColumnName"/>
  <xsl:param name="Percentile"/>
  <xsl:variable name="Pos" select="ceiling($Percentile div 100 * count($Rows))"/>
  <xsl:for-each select="$Rows">
    <xsl:sort select="@*[name()=$ColumnName]" order="ascending" data-type="number"/>
    <xsl:if test="position() = $Pos">
      <xsl:value-of select="@*[name()=$ColumnName]"/>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

This set of templates is just a smattering of what I carry around in my toolkit for use from project to project.  Hopefully one or two of them will turn out to be useful for you. Also, as you can see from the way each template is written, they are highly reusable, so they are excellent candidates for placement in a separate XSL file which is imported into your DVWPs with <xsl:import>.

Series Navigation<< Unlocking the Mysteries of Data View Web Part XSL Tags – Part 19 – Miscellaneous – More Math / Number FunctionsUnlocking the Mysteries of the SharePoint Data View Web Part XSL Tags eBook Now Available >>

Similar Posts

21 Comments

  1. Hi Marc,
    I am inserting Images and some Fields into dataview webpart however here I need is, after getting required
    Images and other Fields into dataview webpart I want to display those Images and Fields in Horizontal
    manner so Please let me know the solution that “how to display those Images and Fields in horizontal manner
    through XSLT “.
    Thanks and Regards
    Kriss

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.