XSLT 列表视图呈现系统概述
上次修改时间: 2011年2月2日
适用范围: SharePoint Foundation 2010
本主题提供 Microsoft SharePoint Foundation 中列表视图呈现系统的概述。在阅读本主题前,您至少应对 XSLT 概念有基本的了解,这些概念包括样式表、模板、参数、节点树和上下文节点。
XSLT 样式表呈现
SharePoint Foundation 随附的 XSLT 样式表位于 %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\LAYOUTS\XSL 中的 .xsl 文件中。其中两个最重要的文件是 vwsytles.xsl 和 fldtypes.xsl。第一个文件提供用于沿行级别向下呈现列表的样式表。第二个文件提供用于在列表视图中呈现特定字段(即单元格)的样式表。main.xsl 中定义了一大组全局 XSLT 变量。
XSLT 样式表分析某些 XML 语言编写的源节点树,并生成不同 XML 语言的结果节点树。在最简单的情况下,源树被转换为结果树。这由 XSLT 模板来完成,每个 XSLT 模板都是一种规则,确定原标记的特定片段转换为结果片段的方式。但是,没必要让转换以结果语言只重新表述全部的仅源节点树的信息。转换可以排除源树中的信息,并可以将非源树中的信息插入结果树。尤其是,XSLT 模板可以组合多个输入节点树中的信息。除了源节点树,每个其他输入节点树也作为参数传递到模板。SharePoint Foundation 的列表视图呈现 XSLT 模板具有两个输入节点树。
源节点树是 视图架构 标记,它定义列表的当前视图。XSLT 处理器在构建结果树时就是分析和遍历此树。因此,在 XSLT 转换期间的任何给定时间,XSLT 处理器的上下文节点是此标记中的一个节点。
thisNode 参数树通过调用模板传递到每个 XSLT 字段呈现模板。此标记包含来自列表的实际数据。呈现字段时,实际字段值就取自该参数。有关 thisNode 参数中标记的全部参考信息,请参阅 dsQueryResponse XML。
有关这些节点树的示例,请参阅 XSLT 转换中的输入和结果节点树示例。
XSLT 模板的层次结构
SharePoint Foundation 中 XSLT 模板的层次结构非常复杂。根据各种因素(其中包括列表类型、选中的列表视图、视图样式以及视图是否包括行分组),呈现列表视图时模板的调用链(通过 xsl:apply-templates 和 xsl:call-template)各有不同。本节说明在用户使用具有以下特征的列表导航至一个页面时这种简单情况下的最简单的可能调用链。
列表类型是 100(通用)。
列表的 BaseViewID 是 1。
视图样式为 0(基本表格)。
没有行分组。
XSLT 样式表的系统通过页面的 PreRender 事件调用。顶级的 XSLT 模板是 vwsytles.xsl 声明的未命名模板,具有以下开始标记。
<xsl:template match="/">
此模板的行为取决于某些 Boolean 测试的结果。但是在最简单的情况下,其为处于 RootTemplate 模式中的模板调用 xsl:apply-templates,并选择当前的上下文节点,即源节点树的根节点。(XmlDefinition 在 main.xsl 中定义为 ".",当前的上下文节点。)
<xsl:apply-templates mode="RootTemplate" select="$XmlDefinition"/>
这样会将 View_Default_RootTemplate 模板应用到 View 元素,该元素是文档元素,也即源节点树的顶级元素。(有关示例,请参阅 XSLT 转换中的输入和结果节点树示例)。以下是此模板的开始标记。
<xsl:template name="View_Default_RootTemplate" mode="RootTemplate" match="View" ddwrt:dvt_mode="root">
此模板构建将呈现列表的 HTML <table>元素。它使用以下行调用次模板。
<xsl:apply-templates select="." mode="full">
<!-- child node omitted -->
</xsl:apply-templates>
这些行为完整模式中的模板调用 xsl:applytemplates 并选择当前的上下文模式,此时仍为 View 元素。在我们的常规列表标准视图的示例场景中,唯一匹配模板是 vwsytles.xsl 的视图模板 部分中的第一个模板。它具有以下开始标记。
<xsl:template match="View" mode="full">
此模板开始呈现列表的某些 HTML 详细信息。最重要的是,它使用以下行调用更多模板。
<xsl:apply-templates select="." mode="RenderView" />
唯一匹配模板是具有以下开始标记的模板。
<xsl:template match="View" mode="RenderView">
对此未命名模板的调用在一个至关重要的方面不同于层次结构中前面的模板。以前的模板仅使用源节点树(定义列表视图)作为信息来源。但若要填写将呈现列表的 HTML 表,需要关于此特定列表的信息,如项目(行)数以及列表中特定字段的值。因此,会向此模板传递一个名为 thisNode 的参数,该参数包含来自 dsQueryResponse 标记的表单中内容数据库的实际列表数据。以后的模板调用或特定模式的模板应用,都会将此相同的参数传递到所调用的模板上。有关 thisNode 参数的内容示例,请参阅XSLT 转换中的输入和结果节点树示例。
该模板循环 thisNode 中的所有行(列表项)。对于每一行,它应用具有项目模式的模板,并向它们传递对视图中所有字段的引用。以下是一些关键行。
<xsl:for-each select="$AllRows">
<xsl:variable name="thisNode" select="."/>
<!-- Matter omitted. The next lines run when the view does not include groups -->
<xsl:apply-templates mode="Item" select=".">
<xsl:with-param name="Fields" select="$Fields"/>
<!-- matter omitted -->
</xsl:apply-templates>
<!-- matter omitted -->
</xsl:for-each>
AllRows 变量是对 thisNode 中 Row 元素的引用。尽管看来当前的节点 "." 通过 select 属性分配到了 thisNode,但这实际上只是对于该节点未向模板传递任何信息时 thisNode 的一个默认值。实际上,dsQueryResponse 会作为参数传递。对于列表中的每一行,会应用具有模式 Item 的模板,并且会向这些模板传递一个 Fields 参数。后者是对源节点树中所有 FieldRef 元素的引用。
具有项目模式的模板有多个,但仅有一个匹配列表类型是 100(常规)且视图样式是 0 的情况。它是 vwstyles.xsl 的行模板 部分中的最前面一个模板。该模板具有以下开始标记。
<xsl:template mode="Item" match="Row">
该模板插入 HTML <tr> 开始和结束标记,这些标记将呈现当前列表项的表格的行。在二者之间,它循环列表项中的所有字段并应用到模式为 printTbleCellEcbAllowed 的每个模板。以下是关键行。
<tr>
<!-- matter omitted -->
<xsl:for-each select="$Fields">
<!-- matter omitted -->
<xsl:apply-templates select="." mode="printTableCellEcbAllowed">
<xsl:with-param name="thisNode" select="$thisNode"/>
</xsl:apply-templates>
<!-- matter omitted -->
</xsl:for-each>
<!-- matter omitted -->
</tr>
唯一的匹配模板具有以下开始标记。
<xsl:template name="FieldRef_printTableCell_EcbAllowed" match="FieldRef"
mode="printTableCellEcbAllowed" ddwrt:dvt_mode="body">
该模板插入 HTML <td> 开始和结束标记以形成当前字段的表格的单元格。它还会向该单元格分配一个级联样式表 (CSS) 类。在开始标记和结束标记之间,它应用模式为 PrintFieldWithECB 的模板,如此处所示。
<td>
<!-- matter omitted -->
<xsl:apply-templates select="." mode="PrintFieldWithECB">
<!-- matter omitted -->
</td>
和层次结构中所有剩余的模板一样,相关匹配模板也在 fldtypes.xsl 中。它具有显示在下一个代码块顶端的开始标记。链中的此模板和剩余模板基于以下各项在 HTML 表中呈现特殊单元格:当前行是标题行还是数据行,字段的类型(如备注或货币)和字段的基类型(如文本或数字),以及字段的呈现方式(例如,呈现为纯文本或呈现为指向显示表单的链接)。以下是数据行中文本字段的剩余模板的开始标记。每个标记通过其前导活动按名称或作为特定模式模板的应用的结果调用。
<xsl:template name="FieldRef_NoMenu_PrintFieldWithECB" ddwrt:ECB="Menu"
match="FieldRef" mode="PrintFieldWithECB" ddwrt:ghost="always">
<xsl:template name="FieldRef_Ecb_PrintFieldWithDisplayFormLink"
ddwrt:ECB="Link" match="FieldRef[@LinkToItem]"
mode="PrintFieldWithDisplayFormLink" ddwrt:ghost="always">
<xsl:template name="FieldRef_PrintField" match="FieldRef" mode="PrintField"
ddwrt:dvt_mode="body" ddwrt:ghost="always">
<xsl:template name="PrintField" ddwrt:dvt_mode="body" ddwrt:ghost="always">
<xsl:template name="FieldRef_Text_body" ddwrt:dvt_mode="body" match ="FieldRef"
mode="Text_body">
最后是最终在 HTML 表的单元格中呈现文本字段的值的模板。以下是此模板的完整标记。
<xsl:template name="FieldRef_Text_body" ddwrt:dvt_mode="body" match ="FieldRef"
mode="Text_body">
<xsl:param name="thisNode" select="."/>
<xsl:choose>
<xsl:when test="@AutoHyperLink='TRUE'">
<xsl:value-of select="$thisNode/@*[name()=current()/@Name]"
disable-output-escaping ="yes"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$thisNode/@*[name()=current()/@Name]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
请注意,模板分支取决于字段是否定义为自动将看上去像 URL 的字符串格式化为 HTML <a> 链接,如果是,则当 XSLT 处理器呈现字段的 HTML 时,将不 会将重要字符(如"<"和"&")替换为其字符实体等效物(< 和 &),默认情况下,相容的 XSLT 处理器通常会这样做。除此问题外,该模板只是通过以下行呈现字段的值。
<xsl:value-of select="$thisNode/@*[name()=current()/@Name]"/>
有关该行的详细讨论,请参阅如何:自定义列表视图中字段的呈现方式。