可以给我一个xsl模板“模式”的例子吗?


72

<xsl:template name="temp_name" mode="mode">

是什么意思mode?我搜索了许多资源,但找不到相应的示例。那么有人可以举例说明吗?

Answers:


91

给模板一个名字和一个模式并没有多大意义

name属性完全标识一个模板,并且不能有两个具有相同名称和不同模式的模板。

mode属性允许使用不同的模式对同一节点进行多次处理

这是一个简短的示例:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="num[position() mod 3 = 1]">
  <tr>
    <xsl:apply-templates mode="copy" select=
     ". | following-sibling::*[not(position() >2)]"/>
  </tr>
 </xsl:template>

 <xsl:template match="*" mode="copy">
  <td><xsl:value-of select="."/></td>
 </xsl:template>

 <xsl:template match="num"/>
</xsl:stylesheet>

当此转换应用于以下XML文档时

<nums>
  <num>01</num>
  <num>02</num>
  <num>03</num>
  <num>04</num>
  <num>05</num>
  <num>06</num>
  <num>07</num>
  <num>08</num>
  <num>09</num>
  <num>10</num>
</nums>

结果是数字显示为三tr(行),每行包含三列(最后一行可能除外):

<tr>
   <td>01</td>
   <td>02</td>
   <td>03</td>
</tr>
<tr>
   <td>04</td>
   <td>05</td>
   <td>06</td>
</tr>
<tr>
   <td>07</td>
   <td>08</td>
   <td>09</td>
</tr>
<tr>
   <td>10</td>
</tr>

在此转换中,任何num位置无法以形式3*k +1(其中k是整数)表示的元素都将被具有空主体的模板匹配,因此不会被处理。

但是,我们要处理num应形成一行单元格的所有元素。为此,我们使用xslt指令对其进行处理:

<xsl:apply-templates mode="copy" select=
 ". | following-sibling::*[not(position() >2)]"/>

这意味着:“不应用于通常将应用(无模式)的所选节点模板,而应应用处于模式的模板copy

因此,我们不会忽略选定的num元素,而是以copy模式处理它们并创建td一行。

模板规则:

<xsl:template match="num"/>

必须重写xslt内置模板(默认处理),否则将导致无法输出num位置不能表示为的节点的字符串值3*k +1

因此,这两个模板都处理了这些节点

<xsl:template match="num"/>

<xsl:apply-templates mode="copy" select=
 ". | following-sibling::*[not(position() >2)]"/>

因此我们得到了想要的结果。

逐步了解一个好的XSLT调试器,以了解如何应用这些模板将是有益的


因此,要清楚您的意思,mode就好比一个过滤器,该过滤器可以确定哪些模板可用于处理节点,而不是特定模板的替代方案之一,这可以从其名称中假定,以及mode能够动态定义使用类型会有所裨益。
Patanjali

@Patanjali,还有其他更好的方法可以动态选择处理。在XSLT 1.0或2.0中,可以使用FXSL库对XSLT进行功能编程(请参阅fxsl.sf.net)。在XPath 3(XSLT 3.0)中,可以将函数作为参数传递给其他函数,即函数项是一类对象,而高阶函数是该语言的标准功能
Dimitre Novatchev

不幸的是,我只能使用XSLT 1.0,因为它是PHP提供的全部,而且我的目标受众主要是使用cPanel和共享服务器,因此无法添加此类扩展。但是,PHP允许从XSLT调用内置的和程序员定义的PHP函数,这可能提供比任何扩展所允许的更为丰富的环境。总有一种完成工作的方法,而局限性迫使我们要富有创造力。
Patanjali

迪米特雷,你是为了消除我对的误解mode
Patanjali

@ Patanjali,FXSL不是扩展,它是用纯XSLT 1.0编写的。有单独的版本-XSLT 1.0和XSLT 2.0。
Dimitre Novatchev

7
<xsl:apply-templates select="phone" />
<xsl:apply-templates select="phone" mode="accountNumber"/>
<xsl:template match="phone">
      <TD>A</TD>
</xsl:template>
<xsl:template match="phone" mode="accountNumber">
      <TD>B</TD>
</xsl:template>

在此处链接一个简单的示例:https : //msdn.microsoft.com/en-us/library/ms256045%28v=vs.110%29.aspx


1
这是一个答案,主要是从XSLT Pocket Guide复制和粘贴信息。OP要求有人用示例进行解释...
Mark Townsend

1
模板作为函数,此处的示例简要地演示了OO类似的名为“ phone”的多态函数。您可以提供不同的模式来拨打不同的电话。
安德鲁

该示例的问题在于,尽管可以进行演示,但需要先了解OP等正在寻求的问题,然后才能理解它。这就是为什么我发现许多MS文档无济于事的原因。但是,因为它没有讨论它的用法mode,所以在这里不做解释就不应该提供它。
Patanjali

2

mode属性允许使用多种方式处理相同的XML元素。

match如果要使用mode属性,模板必须具有属性,因此它们并不意味着模板仅依赖于name属性进行调用。

它们适用于xsl:apply-templates确定哪个xsl:template将响应,因此使用模式的调用将仅调用使用相同模式的模板。没有模式的模板将仅响应没有模式的呼叫。

例如,您可能希望将XMLparagraph元素呈现为HTMLp元素以供查看,而呈现为form用于编辑。

然后可以通过以下方式呈现该视图以供查看:

<xsl:template match="paragraph">
 <p>...</p>
</xsl:template>

通过以下方式匹配paragraphXML文档中的标签:

<xsl:apply-templates />

相反,要渲染以进行编辑,请使用:

<xsl:template match="paragraph" mode="edit">
 <form>...</form>
</xsl:template>

通过致电:

<xsl:apply-templates mode="edit" />

请注意,在示例中,如果要使用non-mode呈现页面的其余部分,则必须显式调用xsl:apply-templatesxsl:template mode="edit"版本paragraph以编辑特定元素。

如果不需要所有XML元素的模式都匹配,请提供一个空模板,例如:

<xsl:template match="*" mode="edit" />

以确保您不会从深匹配中获得“幻像”文本,从而污染了输出。

与任何xsl catchall模板一样,将其放在xsl:template相同模式的all的开头,因为xsl使用最后一个匹配的模板,并且将其放在最后将确保什么都看不到!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.