1,804 articles and 14,802 comments as of Sunday, April 24th, 2011

EndUserSharePoint has combined resources with NothingButSharePoint.com. You can now find End User (Mark Miller), Developer (Jeremy Thake) and IT Pro SharePoint (Joel Oleson) content all in one place!

This site is a historical archive and is no longer being updated. Please update your favorites, bookmarks and RSS feeds.

NothingButSharePoint.com
Thursday, April 1, 2010

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

Author: Marc D. Anderson
http://mdasblog.wordpress.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 template 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) &> 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, '&gt;')">
    <xsl:call-template name="StripHTML">
      <xsl:with-param name="HTMLText" select="concat(substring-before($HTMLText, '&lt;'),
        substring-after($HTMLText, '&gt;'))"/>
    </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 &gt; 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, ' ')) &gt; 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>.

Author: Marc D. Anderson
http://mdasblog.wordpress.com

Marc D. Anderson is a Co-Founder and the President of Sympraxis Consulting LLC, based in Newton, MA.  He has over 25 years of experience as a technology consultant and line manager across a wide spectrum of industries and organizational sizes.  Marc has done extensive consulting on knowledge management and collaboration and what makes them actually work in practice.  Marc is a very frequent “answerer” on the MSDN SharePoint - Design and Customization forum.

Entries in this series:
  1. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 1: Overview
  2. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 2: xsl:template
  3. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 3: xsl:call-template
  4. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 4: xsl:with-param
  5. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 5: xsl:param
  6. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 6: xsl:variable
  7. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 7: xsl:for-each
  8. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 8: xsl:sort
  9. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 9: xsl:if
  10. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 10: xsl:choose
  11. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 11: xsl:value-of
  12. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 12: Miscellaneous - Person or Group Columns
  13. Unlocking the Mysteries of Data View Web Part XSL Tags - Part 13: Miscellaneous - String Functions
  14. Unlocking the Mysteries of Data View Web Part XSL Tags – Part 14: Miscellaneous – ddwrt Namespace Functions
  15. Unlocking the Mysteries of Data View Web Part XSL Tags – Part 15: Miscellaneous – Field / Node Functions
  16. Unlocking the Mysteries of Data View Web Part XSL Tags – Part 16: Miscellaneous – xsl:attribute
  17. Unlocking the Mysteries of Data View Web Part XSL Tags – Part 17: Miscellaneous – xsl:comment and xsl:text
  18. Unlocking the Mysteries of Data View Web Part XSL Tags – Part 18: Miscellaneous – Some Math / Number Functions
  19. Unlocking the Mysteries of Data View Web Part XSL Tags – Part 19: Miscellaneous – More Math / Number Functions
  20. Unlocking the Mysteries of Data View Web Part XSL Tags – Part 20: xsl:import
  21. EUSP eBook Store: First SharePoint Title is Now Available
 

Please Join the Discussion

10 Responses to “Unlocking the Mysteries of Data View Web Part XSL Tags – Part 20: xsl:import”
  1. Steve D says:

    Great series of articles! I hope that more are coming but it feels like you may be winding down.

    Can we maybe see some advanced topics like aggregate data sources and how to reference them in the XSL. You touched on it a tiny bit but it would be great to know in detail how to do it.

    Also, it may not strictly fit into the XSL category but a detailed article on CAML query would be great.

    Just some thoughts.

    • Steve:

      Yes, I’m winding down on this. Given the title of the series (Unlocking the Mysteries of Data View Web Part XSL Tags), I’ve covered most of what I can about the XSL tags, plus quite a few other things. Of course there’s lots more fun with DVWPs that I can talk about, as you suggest.

      M.

  2. KK says:

    Hi Marc,

    I am facing an issue with DataViewWebPart when i customize the XSLT of the webpart , i am not able to export all the cloumns of the webpart. I just get two columns in the excel namely ItemType and Path. I have ten columns. Is there a solution for the same.

    Thanks,
    KK

    • KK, can you post this question in Stump the Panel? (The Stump the Panel link is in the top navigation on this site as well.) Since it doesn’t really apply to this post, it would be best to plant it there. You’ll also have more people looking at it who can help.

      Thanks,
      M.

  3. Marc S says:

    Hi Marc,

    I’ve come across your post and think it might be able to help me out. I’ve converted a list view into its xslt data view to apply some conditional formatting, etc. and now some of the list data is not displaying correctly. I’m getting some ' and &quot; elements in my data instead of the proper apostrophes and quotes.

    I’ve tried importing your xsl FixEscapedChars template into my page but I’m getting the following error:

    Failed setting processor stylesheet : 0×80004005 : Access is denied. Error occurred during compilation of included or imported stylesheet ‘http://mysite/SSRC/CleanUp_EscapeChars.xsl

    I’ve put the template in my Scripting Resource Centre, so I think the permissions there should be alright. Any Ideas?

    Thanks,
    Marc

    • Hey, Marc. Great name.

      Well, it sounds like a permissions error. Are you able to access other files in the Scripting Resource Centre from the same DVWP? Do you have the appropriate “wrapper” around the template(s) in the CleanUp_EscapeChars.xsl file?

      Those questions aside, the solution may be just to add the disable-output-escaping=”yes” attribute to the xsl:select. Check the Unlocking the Mysteries of Data View Web Part XSL Tags – Part 11: xsl:value-of installment in this series for details.

      M.

      • Marc S says:

        Hi Marc,

        Thanks for your response.

        I forgot to mention in my post that the funny thing was that the disable-output-escaping=”yes” attribute didn’t completely fix up the data. It changed the “' ” into “'” and “&quot;” into “"”. That’s why I figured that the xsl template would help.

        (Also, I noticed that in the original post that even it renders the data correctly! Irony. Not sure if this post will do the same so just to clarify &_amp;#39; goes to &_#39; with the disable-output-escaping=”yes”, without the underscores.)

        I’m pretty sure the permissions are good, as there are a few jquery scripts located in the same centre I’m using that work well. It must be something to do with the wrapper. Seeing that i’m not sure what the wrapper should contain? I must read your entire series before continuing to troubleshoot on monday.

        Thanks again, Marc

      • By wrapper, I just meant the enclosing tags I go over in the above article.

        M.

  4. Marc S says:

    Hi Marc

    It looks like I’ve determined the cause of the original problem, the formatting of the text. When I converted the list view to XSLT Data View, the dvt_1.rowview template formatted the xsl:value-of element as follows:

    After going through your xsl series, it looks to me like this xsl is converting a plain text string twice and running into issues. After removing the ddwrt function from the xsl:value-of statement the output is formatted correctly.

    I haven’t solved the ‘Access is denied’ error with the import function, but at least for now my users can read the columns correctly.
    Thanks for your help and this informative series.
    Marc

    • Marc S says:

      Looks like the previous post removed the code snippet. So for clearity the xsl:value-of tag included the disable-output-escaping=”yes” and the select contained the function “ddwrt:AutoNewLine(string(@Description))”

      Cheers,
      Marc S


Notify me of comments to this article:


Speak and you will be heard.

We check comments hourly.
If you want a pic to show with your comment, go get a gravatar!