根据参数应用不同的 XSLT 模板

发布于 2024-10-30 18:46:02 字数 798 浏览 0 评论 0 原文

我有什么?

我有一个 ASP.NET 项目,其中有一个定义了许多模板的 XSLT 文件。根据用户选择,一次仅使用一个模板来在网页上显示内容。它看起来像这样:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:param name="TemplateName"></xsl:param>

      <xsl:template match="Title_Only">
          ...template Title_Only body...
      </xsl:template>

      <xsl:template match="Image_Only">
          ...template Image_Only body...
      </xsl:template>

      <xsl:template match="Title_And_Image">
          ...template Title_And_Image body...
      </xsl:template>
    </xsl:stylesheet>

我想要什么?

我想将模板名称 TemplateName 作为参数传递,并能够在数据上应用相应的模板。

有人可以告诉我如何实现这一目标吗?

What I have?

I am have an ASP.NET project in which, I have an XSLT file with many templates defined. Only one template will be used at a time depending on the user selection to display the content on a web page. It looks something like this:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:param name="TemplateName"></xsl:param>

      <xsl:template match="Title_Only">
          ...template Title_Only body...
      </xsl:template>

      <xsl:template match="Image_Only">
          ...template Image_Only body...
      </xsl:template>

      <xsl:template match="Title_And_Image">
          ...template Title_And_Image body...
      </xsl:template>
    </xsl:stylesheet>

What I want?

I want to pass the template name TemplateName as a parameter and to be able apply the respective template on the data.

Can someone please tell me how can I achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

流年已逝 2024-11-06 18:46:02

您不能在 XSLT 1.0 的匹配模式中使用参数或变量的值。但是,您可以有条件地从单个模板应用模板,如下所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="TemplateName"/>
    <xsl:template match="/">
        <xsl:apply templates select="something[some_condition=$TemplateName]"/>
    </xsl:template>
</xsl:stylesheet>

...然后只需设置模板以分别匹配每种类型的节点。模板将仅应用于与您的 select 表达式匹配的内容,该表达式基于参数。

有条件应用模板的示例

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:variable name="TemplateName" select="'Title_Only'" />
    <xsl:template match="/">
        <xsl:apply-templates select="test/val[@name=$TemplateName]" />
    </xsl:template>
    <xsl:template match="val">
        <xsl:value-of select="@name" />
    </xsl:template>
</xsl:stylesheet>

应用于此输入:

<test>
    <val name="Title_Only" />
    <val name="Image_Only" />
    <val name="Title_And_Image" />
</test>

生成:

Title_Only

...基于 $TemplateName 的值。 (请注意,此示例使用变量,但其思想是相同的。)

使用模式分离模板

如果您确实需要在每种情况下使用完全不同的模板,则可以使用模式。此样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:variable name="TemplateName" select="'Title_Only'" />
    <xsl:template match="/">
        <xsl:choose>
            <xsl:when test="$TemplateName='Title_Only'">
                <xsl:apply-templates select="test/val" mode="Title_Only" />
            </xsl:when>
            <xsl:when test="$TemplateName='Image_Only'">
                <xsl:apply-templates select="test/val" mode="Image_Only" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="test/val" mode="Title_And_Image" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template match="val" mode="Title_Only">
        <xsl:value-of select="@title" />
    </xsl:template>
    <xsl:template match="val" mode="Image_Only">
        <xsl:value-of select="@img" />
    </xsl:template>
    <xsl:template match="val" mode="Title_And_Image">
        <xsl:value-of select="@title" />/
        <xsl:value-of select="@img" />
    </xsl:template>
</xsl:stylesheet>

应用于此源:

<test>
    <val title="some title" img="some image"/>
</test>

生成:

some title

根据参数的值使用所需的模板。

You cannot use the value of a param or variable in a match pattern in XSLT 1.0. However, you could apply templates conditionally from a single template, like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="TemplateName"/>
    <xsl:template match="/">
        <xsl:apply templates select="something[some_condition=$TemplateName]"/>
    </xsl:template>
</xsl:stylesheet>

...and then just set-up templates to match each type of node individually. Templates will be applied only to those things that match your select expression, which is based on the param.

Example of conditionally applying templates

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:variable name="TemplateName" select="'Title_Only'" />
    <xsl:template match="/">
        <xsl:apply-templates select="test/val[@name=$TemplateName]" />
    </xsl:template>
    <xsl:template match="val">
        <xsl:value-of select="@name" />
    </xsl:template>
</xsl:stylesheet>

Applied to this input:

<test>
    <val name="Title_Only" />
    <val name="Image_Only" />
    <val name="Title_And_Image" />
</test>

Produces:

Title_Only

...based on the value of $TemplateName. (Note that this example uses a variable, but the idea is the same.)

Separate templates using modes

If you really need an entirely different template in each case, then use modes. This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:variable name="TemplateName" select="'Title_Only'" />
    <xsl:template match="/">
        <xsl:choose>
            <xsl:when test="$TemplateName='Title_Only'">
                <xsl:apply-templates select="test/val" mode="Title_Only" />
            </xsl:when>
            <xsl:when test="$TemplateName='Image_Only'">
                <xsl:apply-templates select="test/val" mode="Image_Only" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="test/val" mode="Title_And_Image" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    <xsl:template match="val" mode="Title_Only">
        <xsl:value-of select="@title" />
    </xsl:template>
    <xsl:template match="val" mode="Image_Only">
        <xsl:value-of select="@img" />
    </xsl:template>
    <xsl:template match="val" mode="Title_And_Image">
        <xsl:value-of select="@title" />/
        <xsl:value-of select="@img" />
    </xsl:template>
</xsl:stylesheet>

Applied to this source:

<test>
    <val title="some title" img="some image"/>
</test>

Produces:

some title

The desired template is used, based on the value of the param.

你的他你的她 2024-11-06 18:46:02

我想传递模板名称
TemplateName 作为参数并为
能够应用相应的模板
数据。

在 XSLT 1.0 和 XSLT 2.0 中,具有如下构造是非法的:

<xsl:call-template name="{$vTemplateName}"/>

虽然 XPath 3.0 (XSLT 3.0) 引入了函数项和 HOF(高阶函数),但可以在以前的版本中模拟 HOF XSLT。欲了解更多信息,请阅读FXSL主页上的文章。

这里是 FXSL 背后思想的简化示例

<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>

给定此示例 XML,我们有两个模板,一个生成所有 num 元素的总和,另一个生成它们的值级联。我们希望将所需的操作作为参数传递。

以下是如何执行此操作(请注意,源 XML 本身中没有任何内容告诉我们要使用哪个操作):

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

 <xsl:param name="pOp" select="'sum'"/>

 <my:ops>
  <op>sum</op>
  <op>concat</op>
 </my:ops>

 <xsl:variable name="vOps" select=
   "document('')/*/my:ops/*"/>

 <xsl:template match="/">
  <xsl:apply-templates select="$vOps[. = $pOp]">
   <xsl:with-param name="arg1" select="/*/*"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="op[.='sum']">
  <xsl:param name="arg1"/>
  <xsl:value-of select="sum($arg1)"/>
 </xsl:template>

 <xsl:template match="op[.='concat']">
  <xsl:param name="arg1"/>

  <xsl:for-each select="$arg1">
   <xsl:value-of select="."/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

当应用于上面的 XML 文档时,会生成所需的正确结果:< /strong>

55

当我们替换:

 <xsl:param name="pOp" select="'sum'"/>

:

 <xsl:param name="pOp" select="'concat'"/>

并应用新的转换时,再次产生想要的正确结果:

01020304050607080910

请注意

主(使用)模板可以且通常位于单独的 XSLT 样式表文件中,并将导入带有实现操作的模板的样式表。主模板不知道实现了哪些操作(并且不使用带有硬编码名称的 )。

事实上,如果在导入的文件中添加或删除模板,则无需修改主(使用)模板。在这种编程风格中, 指令通常在生成主模板时选择尚未编写的执行模板。

I want to pass the template name
TemplateName as a parameter and to be
able apply the respective template on
the data.

In both XSLT 1.0 and XSLT 2.0 it is illegal to have a construct like:

<xsl:call-template name="{$vTemplateName}"/>

While XPath 3.0 (XSLT 3.0) introduces function items and HOF (higher-order functions), HOF can be emulated in previous verions of XSLT. For more information, do read the articles on the home page of FXSL.

Here is a simplified example of the idea lying behind FXSL:

<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>

Given this sample XML, we have two templates, one which produces the sum of all num elements and the other produces their concatenation. We want to pass the desired operation as a parameter.

Here is how to do this (note that nothing in the source XML itself tells us which operation to use):

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

 <xsl:param name="pOp" select="'sum'"/>

 <my:ops>
  <op>sum</op>
  <op>concat</op>
 </my:ops>

 <xsl:variable name="vOps" select=
   "document('')/*/my:ops/*"/>

 <xsl:template match="/">
  <xsl:apply-templates select="$vOps[. = $pOp]">
   <xsl:with-param name="arg1" select="/*/*"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="op[.='sum']">
  <xsl:param name="arg1"/>
  <xsl:value-of select="sum($arg1)"/>
 </xsl:template>

 <xsl:template match="op[.='concat']">
  <xsl:param name="arg1"/>

  <xsl:for-each select="$arg1">
   <xsl:value-of select="."/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

When applied on the XML document above, the wanted, correct result is produced:

55

when we replace:

 <xsl:param name="pOp" select="'sum'"/>

with:

 <xsl:param name="pOp" select="'concat'"/>

and apply the new transformation, again the wanted, correct result is produced:

01020304050607080910

Do note:

The main (using) template can and typically will be in a separate XSLT stylesheet file and will import stylesheets with templates that implement operations. The main template doesn't know what are the operations implemented (and doesn't use an <xsl:choose> with hardcoded names).

In fact, if templates are added or removed from the imported files, there is no need to modify the main (using) template. In this style of programming the <xsl:apply-templates> instruction often selects for execution templates which were not yet written, when the main template was produced.

美人如玉 2024-11-06 18:46:02

参与 元素。

Get involved with mode attribute in <xsl:apply-templates> element.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文