0

因此,我最近开始在一个项目上使用 XSL 1.0,并且需要遍历节点集,并为每个节点调用具有节点“属性”的模板。
我说“属性”是因为我最终只是制作了一个内部标签,即。我正在迭代的节点集如下所示:

<var>  
  <key>key 1 text here</key>  
  <value>value 1 text here</value>  
</var>  
  ....  
<var>  
  <key>key Nth text here</key>  
  <value>value Nth text here</value>  
</var>  

尽管如果有人认为这样更好,我可以回到类似的东西<var key="keytext" value="valtext" />并使用实际属性(实际上这是我第一次处理这个问题但没有运气的方式)。
无论如何,这个节点集被用来填充表单。用户从填充计划名称下拉菜单的下拉菜单中选择项目名称。一旦用户选择了计划名称,表单上就会有一个名为 Build Variables 的表格,其中填充了该计划的键/值对。如果用户更改计划名称,那么构建变量会发生变化(我已经处理了页面刷新和重新加载并确保旧变量被擦除)并且表中的行数可能会发生变化(一行每个键/值对的表)。

这是 XSL 的相关部分,它获取<var>标签的节点集并将其分配给$variables然后使用 a<for-each>对其进行迭代,获取键/值对并将它们传递给模板“widget_render”(我没有提出widget_render 代码,因为它非常冗长(超过 150 行),并根据传递的参数调用其他模板)。在这种特殊情况下,所有 widget_render 本质上是创建一个文本区域框并使用键或值的内容填充它 - 键的框不能由用户编辑,但它为值创建的框可以。这是代码:

<xsl:variable name="variables" select="bamb-class:getPlanVariables($projVal, $planVal)" />    
<xsl:for-each select="$variables">  
   <xsl:variable name="key" select="./key" />  
   <xsl:variable name="value" select="./value"/>  
   <tr height="30">  
      <td class="datacell" colspan="1">  
         <xsl:call-template name="widget_render">  
            <xsl:with-param name="fieldName" select="concat('keyField[', position(), ']')"/>  
            <xsl:with-param name="renderCmd" select="'input'" />  
            <xsl:with-param name="default" select="$key" />  
            <xsl:with-param name="readOnly" select="'true'" />  
         </xsl:call-template>  
      </td>  
      <td class="datacell" colspan="1">  
         <xsl:call-template name="widget_render">  
            <xsl:with-param name="fieldName" select="concat('valueField[', position(), ']')"/>  
            <xsl:with-param name="renderCmd" select="'input'"/>  
            <xsl:with-param name="default" select="$value" />  
         </xsl:call-template>  
      </td>  
   </tr>  
</xsl:for-each>  

希望这是我正在做的足够的背景,所以这是有道理的。如果没有,请告诉我。

我的问题是:键和值似乎在widget_render 的调用模板中丢失了。这意味着<td>表格中的任何一个标签中都不会出现带有文本的输入框。

但是我可以在适当的标签内做<xsl:value-of select="$key" />,它输出正确的值(信息在那里,只是没有被传递到 widget_render 或其他东西)。没有语句,我目前得到的只是正确的行数,但它们都是空白的。<xsl:value-of select="$value" /><td>value-of

是的,我必须使用 widget_render 模板(不能只是放入<input>标签或其他东西),因为该软件稍后会重新使用 table 上的 widget_render 逻辑来执行其他操作。不,这不是类型冲突或我传入错误类型的东西,我确定了这一点。

我不知道我是否真的错过了一些愚蠢的东西,或者是否有一些我只是不明白的更大的东西,但是这个让我很难过。

简而言之:为什么调用模板(似乎)不起作用并在 for-each 循环中使用键/值对填充表?即使我知道 for-each 正在迭代正确的节点集并且$key$value每次迭代时都有正确的分配。

对此的任何帮助将不胜感激,谢谢!让我知道是否有任何不清楚的地方,或者是否有任何我无意中遗漏的信息需要知道。如果需要,我也可以抛出 widget_render 代码,但我怀疑这实际上对任何人都有帮助。

编辑:这是一个包含整个文件的保管箱的链接:widget_render 从第 119 行开始 https://www.dropbox.com/s/zt3g9idprrca6ak/default-widgets.xml 这是一个很长的模板,它调用的所有其他模板也在那个文件中。

4

1 回答 1

0

所以我设法找到了一个解决方案 - 对我来说似乎有点像黑客,但它可以很好地满足我的需要。

我用这个替换了循环:

<xsl:variable name="planVariables" select="bamb-class:getPlanVariables($projVal, $planVal)"/>
<xsl:call-template name="renderAllRows">
    <xsl:with-param name="i" select="1"/>
    <xsl:with-param name="count" select="count($planVariables)"/>
    <xsl:with-param name="planVariables" select="$planVariables"/>
</xsl:call-template>

然后调用 renderAllRows 递归调用自身来模拟xsl:for-each循环,直到表中的所有行都被渲染。

<xsl:template name="renderAllRows">
    <xsl:param name="i" />
    <xsl:param name="count" />
    <xsl:param name="planVariables" />
    <xsl:if test="$i &lt;= $count">
    <xsl:call-template name="renderRow" >
            <xsl:with-param name="rowNum" select="$i"/>
            <xsl:with-param name="planVariables" select="$planVariables"/>
        </xsl:call-template>
    </xsl:if>
<!-- recursion here -->
    <xsl:if test="$i &lt;= $count">
        <xsl:call-template name="renderAllRows">
            <xsl:with-param name="i" select="$i + 1"/>
            <xsl:with-param name="count" select="$count"/>
            <xsl:with-param name="planVariables" select="$planVariables"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

<xsl:template name="renderRow">
    <xsl:param name="rowNum"/>
    <xsl:param name="planVariables"/>
    <xsl:variable name="key" select="exsl:node-set($planVariables)[position()=$rowNum]/key"/>
    <xsl:variable name="value" select="exsl:node-set($planVariables)[position()=$rowNum]/value"/>
    <tr height="30">
        <td class="datacell" colspan="1">
            <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="concat('keyField[', $rowNum, ']')"/>
                <xsl:with-param name="renderCmd" select="'input'" />
                <xsl:with-param name="default" select="$key" />
                <xsl:with-param name="readOnly" select="'true'" />
            </xsl:call-template>
        </td>
        <td class="datacell" colspan="1">
            <xsl:call-template name="widget_render">
                <xsl:with-param name="fieldName" select="concat('valueField[', $rowNum, ']')"/>
                <xsl:with-param name="renderCmd" select="'input'"/> 
                <xsl:with-param name="default" select="$value" />
            </xsl:call-template>
        </td>
    </tr>                
</xsl:template>

这让一切正常工作,对 widget_render 的调用正在查看正确的上下文,创建它们应该的文本框并填充它们。感谢 Jirka 提供的帮助我解决此问题的提示。

于 2013-07-22T16:23:00.523 回答