Hi all. This is Greg Chan, Program Manager on the SharePoint team, for the third part in this List View series. In this post I’m excited to have one of the key architects of the new XSLT List View Web Part (XLV) talk more about its architecture. Here is what he has to say:
Hi! I’m Eric Andeen, a developer on the SharePoint team. I’m going to describe in a little more detail how the XSLT List View Web Part (XLV) works, and how that affects people building and using SharePoint sites.
List View XML and minimal markup
As Greg mentioned in Part I, the XLV is the new list view technology in SharePoint 2010, replacing the List View Web Part (LVWP). Since the XLV is the replacement for the LVWP, it needs to do all the same things, as well as adding new capabilities. The best place to start this discussion is with some of the things that haven’t changed.
The markup required to specify a LVWP is pretty simple – we need to know which list the LVWP is displaying, and we need to know about the view. The list can be identified by name, URL or guid identifier, but the view is a little more complex, and is specified in XML. This is an example of the ViewXML of the default view of an announcements list:
<View Name="{F5D7FCD1-BEFE-42b5-9339-4F4F3C6A38FE}" DefaultView="TRUE" DisplayName="All Items" Url="/Lists/Announcements/AllItems.aspx">
<Query>
<OrderBy>
<FieldRef Name="Modified" Ascending="FALSE"/>
</OrderBy>
</Query>
<ViewFields>
<FieldRef Name="Attachments"/>
<FieldRef Name="LinkTitle"/>
<FieldRef Name="Modified"/>
<FieldRef Name="Number"/>
</ViewFields>
<RowLimit Paged="TRUE">30</RowLimit>
</View>
The primary use of the ViewXML is to generate the SPDataSource that gets the data, but it is also used in the xsl transform to turn the raw xml data returned into presentable HTML, as we will see below. The part of the ViewXML that’s most important to this discussion is the <ViewFields> tag – it tells SharePoint which fields are in the view.
Schema Independent XSL
The XLV is now the default list view technology in SharePoint, and that means it has to scale as well as the LVWP. The only way that’s possible is for the XLV to render any uncustomized, out of the box view using a single XSLT. An uncustomized XLV has no <xsl> property at all – SharePoint supplies the same shared XSLT that is used to render every other XLV. The XSLT responsible for this lives on your server at http://<myserver>/_layouts/xsl/main.xsl – go ahead and open it up and look at it, as well as the xsl:import files vwstyles.xsl and fldtypes.xsl that do most of the work.
Before we discuss how the XLV’s schema independent XSLT works, it’s worth considering how typical, schema dependent XSLT like that used in the DataFormWebPart works. In order to render a tabular view of rows and columns, any technology, XSLT included, needs to iterate through the rows, and in each row, it needs to iterate through the columns, rendering each part appropriately. The XML we’re transforming looks like this:
<Rows>
<Row @Field1="Hello" @Field2="World!" @Field3="" />
<Row @Field1="Some" @Field2="More" @Field3="Data" />
<Row @Field1="Yet" @Field2="More" @Field3="Data" />
</Rows>
The interesting portion of a typical XSLT for this XML looks like this:
<xsl:for-each select="$Rows">
<tr>
<td>
<xsl:value-of select="@Field1"/>
</td>
<td>
<xsl:value-of select="@Field2"/>
</td>
<td>
<xsl:value-of select="@Field3"/>
</td>
</tr>
</xsl:for-each>
The output HTML is a 3×3 table:
|
Hello
|
World!
|
|
|
Some
|
More
|
Data
|
|
Yet
|
More
|
Data
|
This XSLT is schema dependent because it iterates through the list of columns by naming each one explicitly. Using this XSLT, the schema of the rendered list is fixed; it’s not possible to change the set of fields without changing the XSLT.
The schema independent XSLT that the XLV uses iterates through the rows pretty much the same way as the example above, but it iterates through the columns quite differently. When the XLV renders the list, the XML passed in to the transformation engine includes not just the data in the <Rows> collection; it also includes the ViewXML shown above, enhanced with additional schema information. There are several instances of the field iterator in the XSLT to accommodate different view styles, but they all look something like this:
<xsl:for-each select="ViewFields/FieldRef">
<xsl:apply-templates mode="PrintField" select=".">
<xsl:with-param name="thisNode" select="$thisNode"/>
</xsl:apply-templates>
</xsl:for-each>
The “ViewFields" referenced in the <xsl:for-each> is the <ViewFields> tag in the enhanced ViewXML markup, and the $thisNode variable refers to the current row in the Rows collection. The XSLT also contains a set of templates for rendering the fields. A simplified version of those field templates would look like this:
<xsl:template match="FieldRef" mode="PrintField">
<xsl:param name="thisNode" select="."/>
<td>
<xsl:apply-templates match="FieldRef" mode="PrintValue">
<xsl:with-param name="thisNode" select="$thisNode"/>
</xsl:apply-templates>
</td>
</xsl:template>
<xsl:template match="FieldRef" mode="PrintValue>"
<xsl:param name="thisNode" select="."/>
<xsl:value-of select="$thisNode/@*[name()=current()/@Name]"/>
</xsl:template>
The first template outputs the <td> tag and then calls the next template to output the actual value. The second template is where things get interesting. In the schema dependent example above, the values were all named explicitly – @Field1, etc. We can’t do that in the schema independent XSLT, so instead, we use the FieldRef node in the ViewFields markup to get the appropriate attribute from the row. $thisNode is the row of data we’re looking at, and the current XSLT context (.) is the FieldRef node for the field we’re rendering. So the value of the funky xpath expression above – $thisNode/@*[name()=current()/@Name] – is the value of the attribute in the Row tag for the current field – exactly what we want. $thisNode is the row of data we’re looking it; @* is the xpath attribute axis, and [name()=current()/@Name] selects the one attribute whose name matches the @Name attribute of the current context – the FieldRef node.
The actual XSLT for the XLV has to do more than just render simple values inside unadorned <td> tags – it has to render field headers, list item menus on title fields, proper CSS classes on <td> and other tags, etc. It also has to render some field types (hyperlink, person, etc.) differently from simple text fields. All this is done through the same basic mechanism as in the simplified version above – the fields iterator calls a template to render the field, which in turn calls into a series of other templates. Some of the simpler differences make use of <xsl:apply-templates> to select the right template – the template that renders date fields has a match="FieldRef[@Type='DateTime']" instead of just match="FieldRef", for example. More complex checks make use of <xsl:if> and <xsl:choose> along with <xsl:call-template> to call the right template.
XLV Model
The following diagram sums up the process which turns list data and XSLT into the view you see when you browse to a SharePoint page. The data comes from an SPDataSource control, but unlike the DataFormWebPart, the SPDataSource control is dynamically generated from the ViewXML in the diagram below. The SPDataSource control produces an XML rowset containing the list data. The ViewXML gets enhanced with list schema information and added to the XML rowset containing the data. The XSLT is compiled into an XslCompiledTransform – and since we always use the same XSLT, it’s only compiled once per web server. The XML rowset, with both the data and the enhanced ViewXML, is passed into the XslCompiledTransform, and the HTML output goes into the page stream and onto the screen of your browser.
news, site) is at it again, offering another way to migrate your content into another CMS. This time it’s for those of you who have a blog but are being lulled by the sweet song of SharePoint 2010.
Read full story…

Tags: Blogs, Social Networks