XSL: передача переменных между шаблонами - PullRequest
12 голосов
/ 30 января 2010

Можно ли передать переменную из одного родительского шаблона в его дочерний элемент?

<xsl:template match="structure">
  <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable>
  <xsl:apply-templates select="folders">
    <xsl:with-param name="var1" select="'{var}'"/>
  </xsl:apply-templates>
</xsl:template> 

этот шаблон будет соответствовать:

<xsl:template match="folder">
  <xsl:param name="var1"/>
  <xsl:value-of select="$var1"/>
</xsl:template>

Вы видите, я хочу использовать var в качестве var1 в совпавшем шаблоне.

Как я могу сделать эту работу?

редактирование: структура такая:

<structure path="C:\xampplite\htdocs\xampp">
  <folders>
    <folder name="img">
      <date>01/28/10 21:59:00</date>
      <size>37.4 KB</size>
    </folder>
 </folders>
</structure>

edit2:

<xsl:template match="folder">
<xsl:variable name="var1"><xsl:value-of select="../../@path"/></xsl:variable>
<xsl:variable name="var2"><xsl:value-of select="@name" /></xsl:variable>
<xsl:variable name="var3"><xsl:value-of select="$var1"/>\<xsl:copy-of select="$var2"/>    </xsl:variable>
 <th colspan="2" align="left"  bgcolor="#FF5500"><a onclick="foo('{$var3}')"><xsl:value-of select="$var3"/></a></th>

в функции jscript строка без обратной косой черты. кто-нибудь знает почему?

C: xampplitehtdocsxamppimg

Ответы [ 4 ]

30 голосов
/ 30 января 2010

Вы можете передавать параметры именованным шаблонам, которые вы вызываете через <xsl:call-template>, например ::10000 *

<xsl:call-template name="name">
   <xsl:with-param name="param" select="xpathexpr"/>
</xsl:call-template>

<xsl:template name="name">
   <xsl:param name="param"/>
   ...
</xsl:template>

Когда вы вызываете именованный шаблон, контекстный узел является текущим контекстом. Таким образом, чтобы вызвать именованный шаблон для дочерних узлов, вам нужно изменить текущий контекст с помощью <xsl:for-each>:

<xsl:for-each select="child">
   <xsl:call-template name="name">
      <xsl:with-param name="param" select="xpathexpr"/>
   </xsl:call-template>
</xsl:for-each>

В вашем случае, тем не менее, нет необходимости передавать параметры, поскольку переменная, которую вы пытаетесь использовать, является чем-то, к чему можно перейти из контекстного узла. И вам не нужно использовать все эти переменные (и при этом вы не должны давать переменной имя, столь бесполезное, как var1):

<xsl:template match="folder">
   <xsl:variable name="linkarg" value="concat(../../@path, '\\', @name)"/>
   <xsl:variable name="linktext" value="concat(../../@path, '\', @name)"/>
   <th colspan="2" align="left"  bgcolor="#FF5500">
      <a onclick="foo('{$linkarg}')">
         <xsl:value-of select="$linktext"/>
      </a>
   </th>
</xsl:template>

Кроме того, у меня будет соблазн использовать ancestor::structure[1]/@path вместо ../../@path, потому что это делает намерение намного более явным; ваша версия означает «получить атрибут path из родительского элемента родительского элемента», а моя версия означает «проходить по цепочке элементов-предков до тех пор, пока вы не найдете первый с именем structure и не получите его атрибут path. «

9 голосов
/ 09 ноября 2012

При использовании XSLT 2.0 можно передавать параметры дочерним шаблонам, добавляя tunnel="yes" к <xsl:with-param .../> на месте вызова и к элементу </xsl:with-param .../> в вызываемом шаблоне. Просто сделай:

<xsl:template match="folder">
  <xsl:param name="var1" tunnel="yes"/> <!-- note the 'tunnel="yes"' attribute here! -->
  <xsl:value-of select="$var1"/>
</xsl:template>

<xsl:template match="structure">
  <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable>
  <xsl:apply-templates select="folders">
    <xsl:with-param name="var1" select="$var" tunnel="yes"/> <!-- note the 'tunnel' attribute here, too! -->
  </xsl:apply-templates>
</xsl:template>

Дополнительную информацию см. В разделе 10.1.2 Tunnel parameters в спецификации XSLT 2.0.


Расширенный пример

С параметрами туннеля вы можете даже сделать это:

<xsl:template match="structure">
   <!-- same as before -->
</xsl:template>

<xsl:template match="folder">
  <!-- Look, ma, no param declaration! -->
  <!-- ... -->
  <xsl:apply-templates select="date"/>
  <!-- ... -->
</xsl:template>

<xsl:template match="folder/date">
   <xsl:param name="var1" tunnel="yes"/>
   <xsl:value-of select="$var1"/>
</xsl:template>

Из-за атрибута tunnel, параметр var1 передается из исходного шаблона через все промежуточные шаблоны в шаблон "folder/date".

Просто помните, что объявление атрибута tunnel="yes" должно присутствовать как в <xsl:param name="var1" tunnel="yes"/> , так и в соответствующем атрибуте <xsl:with-param name="var1" tunnel="yes" select="..."/>.

5 голосов
/ 30 января 2010

Две проблемы с шаблоном structure:

  1. Вы применяете шаблоны, выбрав folders, но у них есть соответствующий шаблон на folder. Либо измените его на folder, либо, если у вас есть шаблон folders, убедитесь, что он передает значение параметра var1 в шаблон folder.
  2. Ваш with-param @select использует '{var}', который выбирает эту буквальную строку {var}. Если вы хотите выбрать переменную var, удалите окружающие кавычки и фигурные скобки и просто выберите $var.

Внесены изменения в шаблон structure:

<xsl:template match="structure">
  <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable>
  <xsl:apply-templates select="folder">
    <xsl:with-param name="var1" select="$var"/>
  </xsl:apply-templates>
</xsl:template>
4 голосов
/ 30 января 2010

Точный код для вызова будет:

<xsl:template match="structure">
  <xsl:variable name="var"><xsl:value-of select="@path" /></xsl:variable>
  <xsl:apply-templates select="folders/folder">
    <xsl:with-param name="var1" select="$var"/>
  </xsl:apply-templates>
</xsl:template>

Другим способом доступа к атрибуту @path корневого узла будет изменение вашего шаблона на:

<xsl:template match="folder">
  <xsl:value-of select="../../../@path"/>
</xsl:template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...