views:

860

answers:

1

I'm trying to change rendering of a list column on list view page.

After a few tutorials and some hair pulling I managed to create an xslt for a calculated and currency field (from fldtypes_XXXXXX.xsl):

<xsl:template match ="FieldRef[@Name='MarkCalc']" mode="Text_body">
  <xsl:param name="thisNode" select="."/>
  <xsl:value-of select="$thisNode/@*[name()=current()/@Name]" disable-output-escaping ="yes"/>
</xsl:template>

<xsl:template match="FieldRef[@Name='CurrencyTest']" mode="Number_body">
  <xsl:param name="thisNode" select="."/>
  <b><xsl:value-of disable-output-escaping="yes" select="$thisNode/@*[name()=current()/@Name]" /></b>
</xsl:template>

Then I tried to do the same for a lookup field, but it just won't work. This is my last attempt (I copied it from SharePoint designer). What am I missing?

<xsl:template match="FieldRef[(@Encoded) and @Name='Lookup1']" mode="Lookup_body">
  <xsl:param name="thisNode" select="."/>
  <b><xsl:value-of select="$thisNode/@*[name()=current()/@Name]" disable-output-escaping="yes" /></b>
</xsl:template>
+1  A: 

As it turns out, this is entirely xsl problem.

Xsl processor chooses template to use based on "match" and "mode" attributes. When two or more templates match, the one to use is chosen on priority. By default there are three levels of priorities that are assigned based on how specific your match is.

From http://www.codetoad.com/xml/xslt8.asp:

  • Patterns that match a class of nodes, such as *, which matches all elements, are assigned an implicit priority of -0.5

  • Patterns that match nodes according to their name, such as Character, which matches elements, are assigned an implicit priority of 0

  • Patterns that match nodes according to their context, such as CastMember/Character, which matches elements whose parent is a element, are assigned an implicit priority of 0.5

When assigning priorities based on patterns, it doesn't matter how specific the context information is: if you specify any context for a node then the template has a priority of 0.5. For example, Description/Link/Character has exactly the same priority as Description//Character.

In SharePoint there are two templates for lookup fields

<xsl:template name="FieldRef_Lookup_body" match="FieldRef" mode="Lookup_body" ddwrt:dvt_mode="body">...

and

<xsl:template match="FieldRef[@Encoded]" mode="Lookup_body" ddwrt:dvt_mode="body">

First one has priority 0 (match according to its name), second one has priority 0.5 (match according to context).

My custom template that should override encoded lookup

<xsl:template match="FieldRef[(@Encoded) and @Name='Lookup1']" mode="Lookup_body">...

also has default priority of 0.5 (remember, "...it doesn't matter how specific the context information is..."), so xsl processor chooses the last one defined(*).

To overcome this you can use attribute priority and set it to higher value than the default template. In my case, I set it to 1.

<xsl:template match="FieldRef[(@Encoded) and @Name='Lookup1']" priority="1" mode="Lookup_body">...



(*) Apparently SharePoint loads custom templates before loading its own. Whether this was a choice based on some technical criteria or to ensure I learn xsl, remain mystery.

Luc