Search code examples
sharepointxsltsharepoint-2007filteringsharepoint-designer

Sharepoint XSLT Dynamic filtering


I'm trying to create a dynamic row filter based on a variable. I have the following code:

<xsl:variable name="filter" select="contain(@Title, 'title1') or contain(@Title, 'title2')"/>
<xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row[string($filter)]" />

This unfortunately doesn't seem to work and I end up with all rows. I'm guessing the filter doesn't actually get applied, since I can copy and paste the output of the $filter variable, copy and paste it in the Row[] and it works as expected.

Anyone tried to do this before?

In case you're wondering the filter variable is actually created using a template that splits a string like: title1 - title2 - title3 and returns a string like: contain(@Title, 'title1') or contain(@Title, 'title2') or contain(@Title, 'title3')

Any help would be greatly appreciated!


Solution

  • You can't do what you seem to be attempting here. An XPath expression is atomical, you can't save parts of it and re-use them (apart from that it is contains(), not contain()).

    You need something like this:

    <xsl:variable name="Rows" select="
      /dsQueryResponse/Rows/Row[
        contains(@Title, 'title1') or contains(@Title, 'title2')
      ]
    " />
    

    Your "filter" does not work because if $filter is a string, then it is a string, nothing else. It does not get a magical meaning just because it looks like XPath. ;-)

    This

    <xsl:variable name="Rows" select="/dsQueryResponse/Rows/Row[string($filter)]" />
    

    evaluates to a non-empty string as the predicate. And any non-empty string evaluates to true, which makes the expression return every node there is.

    If you want a dynamic filter based on an input string, then do this:

    <xsl:variable name="filter" select="'|title1|title2|title3|'" />
    <xsl:variable name="Rows" select="
      /dsQueryResponse/Rows/Row[
        contains(
          $filter,
          concat('|', @Title, '|')
        )
      ]
    " />
    

    The use of delimiters also prevents "title11" from showing up if you look for "title1".

    Make sure your filter always starts and ends with a delimiter, and use a delimiter that is reasonably unlikely to ever occur as a natural part of @Title. (For example, you could use &#13;. If your title cannot be multi-line this is pretty safe.)