Unlocking the Mysteries of Data View Web Part XSL Tags – Part 15 – Miscellaneous: Field / Node Functions

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

Cross-posted from EndUserSharePoint.com

Another day, another wunnerful article about the DVWP.  This time, I’m going to cover some of the most useful “built-in” Field / Node functions.  These are functions that are a part of XSL itself and help you work with nodes in the result set.  A node is a geekier term for a thing in an XML file.  Pretty much anything can be a node in XML: the entire document, a “row”, a “column”, etc.  Remember that XML provides the data and the XSL does the transformation on it, thus XSLT. Transformation is just deciding how you’d like to deal with the data coming in from the XML file.

position()

Most often, you’ll see this in the XSL like so: position() mod 2 = 1 position() returns the current item’s position in the rowset. So if the item is number 7 of 312, position() returns 7. The value is used in the position() mod 2 = 1 clause to determine if the row is even or odd, usually for alternating row formatting using the ms-alternating CSS class.

<tr>
  <xsl:if test="position() mod 2 = 1">
    <xsl:attribute name="class">ms-alternating</xsl:attribute>
</xsl:if>

The <xsl:attribute> tag (which I failed to cover in the main part of the series) allows you to set an attribute of an HTML object.

current()

current() represents the current node in the nodeset.  What that means is that it’s the item you are currently working with.  You’ll see things like this when you set things via the dialogs:

<xsl:variable name="dvt_ParentRow" select="current()" />

The other way that you can use current() is to distinguish between columns in different lists when you have an AggregateDataSource:

<xsl:variable name="Rows" select="/dsQueryResponse/Annual/Rows/Row[@Title  = current()/@Title]"/>

What the above mean is that you want to select the items in the Annual list where the Title matches the Title in the current item.  This is basically what happens when you “join” two lists in SharePoint Designer.  It’s not like a database join, but just a filter on the second list per item value in the first.

name()

You can use name() to return the name of a node.  But the cooler thing you can do with it is variably reference columns.

Here’s an example of something I built for a project that used name() to variably sort the rows.  I had links at the top of each column in the DVWP, each of which redirected back to the same page with different values for the SortField and AscDesc.  (There’s more to this; if you’d like to understand the example better, see my blog post Sorting Displays in Data View Web Parts.)

<xsl:sort select="@*[name()=$SortField]" order="{$AscDesc}" />

By passing in different column names for SortField and either [ascending | descending] for AscDesc, I was able to sort the rowset by any column and in either ‘direction’.  You might say “Yeah, but List View Web Parts give you that out of the box.”  That’s certainly true, but in the case, there was a *lot* of other stuff going on in the DVWP and this gave us much finer control.

count()

count() is considered a Field / Node function rather than a Math / Number function.  That sort of makes sense, but I still always look for it in the wrong place in the XPath Expression Builder when I’m showing someone how to use it.  (BTW, the descriptions in the XPath Expression Builder are often for the birds, and even after almost four years of availability, there are still “bugs” in them.  First one to email me with an example wins a free copy of the jQuery Library for SharePoint Web Services.)

Using count() is pretty straightforward, and simply returns the number of nodes (generally items) in the nodeset:

<xsl:variable name="NumberOfRows" select="count($Rows)" />

As with the other articles in the series, I’m not going to cover all of the functions available in the field / Node group.  Hopefully, though, going over this subset will show you a few more neat things you can do in a DVWP.

In the next article, I’ll go over some more bits and pieces that we haven’t covered yet.  It’ll be a mystery until then.

Series Navigation<< Unlocking the Mysteries of Data View Web Part XSL Tags – Part 14 – Miscellaneous: ddwrt Namespace FunctionsUnlocking the Mysteries of Data View Web Part XSL Tags – Part 16 – <xsl:attribute> >>

Similar Posts

9 Comments

  1. This is excellent! but I think i’m missing something. I’m trying to use this to join in some detail from a matching row on my lookup source list. If my parent list has a lookup column called ApplicantID pointing to the ID column of the lookup source. How do I pull in column ApplicantName from that source list.

    this code does not compile, but wanted to post it before I go searching for what’s wrong.

    I’m inside my dataview where my parent has the lookup column ApplicantID. And I’m wanting to fetch the matching ApplicantName.

    <xsl:variable name="ApplicantName" select="$ApplicantRow/@ApplicantName"

    Thank You!

    1. jcnet:

      It sounds like you want something like this:

      <xsl:variable name="ApplicantName" select="$ApplicantRow[@ApplicantID = current()/@ApplicantID]/@ApplicantName"/>
      

      The code in the brackets acts as a filter, saying where the ApplicantID in the $ApplicantRow nodeset matches the ApplicantID in the current node.

      M.

      1. Hi Mark,

        We have a company intranet site, and it has a document library with the xslt code to get the total number of documents in a document library in Sharepoint 2007.

        Recently it wasn’t giving the correct total, evening though you add new docs, the number does not increment.

        Is there a code on how to get the count?

        Thanks for the trouble

        Leroy M

        1. Leroy:

          The XPath to get the count of items in a nodeset is simply count(nodeset). Without seeing your code, I can’t really tell you what your issue might be. I’d also check the filters on the DVWP.

          M.

  2. Hi Mark,

    I am trying to get a count of items that are past their due date. I have a “status” column that is either “Open” or “Closed” and a second column with “Agreed Response Date” in (formatted as date/time in WSS 3.0). I am looking for items that are still open and that have a due date that is less than the current date. I can easily find the open items,

    and I can test whether the due date has passed:

    I am baffled as to how to get the two together, as I keep getting type mismatches if I try to put a count on the $DateCompare variable.

    Any help would be much appreciated!

    Rob

    1. Rob:

      You’ll want to do something like this. It’s not going to be exactly right, but it should give you the idea.

      <xsl:variable name="DateCompare" ... your "Past due" determination
      <xsl:value-of select="count($Rows[@Status ='Open' and $DateCompare = 'Y'])"/>
      

      replacing “Y” with whatever you’re returning in your calculation which indicates a past due item.

      M.

      1. Thanks Marc,

        I need to pass the count of the items past their due date to a variable, used in a template for display of the result. My DateCompare variable returns a true or false for each item as it is a simple logical test:
        xsl:variable name=”DateCompare” select=”ddwrt:FormatDateTime(string(@Agreed_x0020_response_x0020_date),1033,’ddMMyyyy’)< ddwrt:FormatDateTime(string(ddwrt:Today()),1033,’ddMMyyyy’)”

        I have tried:
        xsl:variable name=”OpenLate” select=”count($Rows[@Status =’Open’ and $DateCompare = ‘true’])”
        but this returns a 0 value, probably a newbie mistake but any ideas?

        Thanks
        Rob
        Hopefully the items pasted from XSL will remain visible without the greater than and less than brackets!

        1. Rob:

          To debug this, display what value you are getting in the DateCompare variable to see what it contains. It definitely won’t be the string ‘true’. My guess is that it will be 0 or 1, but it’s best if you figure it out in your environment.

          Also, comparing two dates with the format ‘ddMMyyyy’ will give you incorrect results. You need to use the format ‘yyyyMMdd’.

          M.

          1. Many thanks Marc,

            the following works (or appears to!):
            xsl:variable name=”OpenLate” select=”count(/dsQueryResponse/Rows/Row[@Status =’Open’ and ddwrt:FormatDateTime(string(@Agreed_x0020_response_x0020_date),1033,’yyyyMMdd’)< ddwrt:FormatDateTime(string(ddwrt:Today()),1033,’yyyyMMdd’)])”

            Thanks for the format corrections, the previous format try did indeed give gibberish.

            Regards

            Rob

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.