循环中的XSLT动态节点名称

时间:2011-09-08 12:32:40

标签: xml xslt xpath loops

有没有人知道是否可以循环遍历模板并根据迭代次数提取节点值。例如,我有以下XML结构:

<nodes>
  <node>
    <label1>Label a</label1>
    <value1>Value a</value1>
    <label2>Label b</label2>
    <value2>Value b</value2>
    <label3>Label c</label3>
    <value3>Value c</value3>
    etc...
  </node>
</nodes>

总共有20个标签/值对数据。我想通过XSLT在表中输出这些。通过循环模板20次(除非有更好的方法)。

我下面的代码有效,但在输出值时不会接受动态数字(例如

<xsl:value-of select="$node/label$index"/>

到目前为止,这是代码:

<xsl:param name="currentPage"/>
<xsl:variable name="numberOfPairs" select="20" />

<xsl:template match="/">
  <table>
    <xsl:call-template name="outputData">
      <xsl:with-param name="node" select="$currentPage" />
    </xsl:call-template>
  </table>
</xsl:template>

<xsl:template name="outputData">
  <xsl:param name="node" select="." />
  <xsl:param name="index" select="1" />
  <tr>
    <td><xsl:value-of select="$node/label1"/></td>
    <td><xsl:value-of select="$node/value1"/></td>
  </tr>
  <xsl:if test="$index &lt;= $numberOfPairs">
    <xsl:call-template name="outputData">                         
      <xsl:with-param name="node" select="$node" />
      <xsl:with-param name="index" select="$index + 1" />                             
    </xsl:call-template>
  </xsl:if>
</xsl:template>

有人可以建议解决这个问题吗?

2 个答案:

答案 0 :(得分:3)

<xsl:output method="xml" indent="yes" />

<xsl:template match="/">        
    <table>
        <xsl:apply-templates select="nodes/node/*[starts-with(name(), 'label')]"/>
    </table>
</xsl:template>

<xsl:template match="*">

    <xsl:variable name="index" select="substring(name(), 6)"/>

    <tr>
        <td>
            <xsl:value-of select="."/>
        </td>
        <td>
            <xsl:value-of select="following-sibling::*[name() 
                          = concat('value', $index)]"/>
        </td>
    </tr>
</xsl:template>

输出:

<table>
  <tr>
    <td>Label a</td>
    <td>Value a</td>
  </tr>
  <tr>
    <td>Label b</td>
    <td>Value b</td>
  </tr>
  <tr>
    <td>Label c</td>
    <td>Value c</td>
  </tr>
</table>

答案 1 :(得分:1)

此转化

<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:param name="pLimit" select="20"/>

 <xsl:template match="/">
   <xsl:apply-templates select=
    "/*/*/*[starts-with(name(), 'label')
          and
            not(substring-after(name(), 'label') > $pLimit)
           ]"/>
 </xsl:template>

 <xsl:template match="*[starts-with(name(), 'label')]">
  <tr>
   <td><xsl:value-of select="."/></td>
   <td><xsl:value-of select="following-sibling::*[1]"/></td>
  </tr>
 </xsl:template>
</xsl:stylesheet>

应用于此XML文档(类似于提供的,但有21个标签值对):

<nodes>
    <node>
        <label1>Label a</label1>
        <value1>Value a</value1>
        <label2>Label b</label2>
        <value2>Value b</value2>
        <label3>Label c</label3>
        <value3>Value c</value3>
        <label4>Label d</label4>
        <value4>Value d</value4>
        <label5>Label e</label5>
        <value5>Value e</value5>
        <label6>Label f</label6>
        <value6>Value f</value6>
        <label7>Label g</label7>
        <value7>Value g</value7>
        <label8>Label h</label8>
        <value8>Value h</value8>
        <label9>Label i</label9>
        <value9>Value i</value9>
        <label10>Label j</label10>
        <value10>Value j</value10>
        <label11>Label k</label11>
        <value11>Value k</value11>
        <label12>Label l</label12>
        <value12>Value l</value12>
        <label13>Label m</label13>
        <value13>Value m</value13>
        <label14>Label n</label14>
        <value14>Value n</value14>
        <label15>Label o</label15>
        <value15>Value o</value15>
        <label16>Label p</label16>
        <value16>Value p</value16>
        <label17>Label q</label17>
        <value17>Value q</value17>
        <label18>Label r</label18>
        <value18>Value r</value18>
        <label19>Label s</label19>
        <value19>Value s</value19>
        <label20>Label t</label20>
        <value20>Value t</value20>
        <label21>Label u</label21>
        <value21>Value u</value21>
    </node>
</nodes>

生成想要的正确结果

<tr>
   <td>Label a</td>
   <td>Value a</td>
</tr>
<tr>
   <td>Label b</td>
   <td>Value b</td>
</tr>
<tr>
   <td>Label c</td>
   <td>Value c</td>
</tr>
<tr>
   <td>Label d</td>
   <td>Value d</td>
</tr>
<tr>
   <td>Label e</td>
   <td>Value e</td>
</tr>
<tr>
   <td>Label f</td>
   <td>Value f</td>
</tr>
<tr>
   <td>Label g</td>
   <td>Value g</td>
</tr>
<tr>
   <td>Label h</td>
   <td>Value h</td>
</tr>
<tr>
   <td>Label i</td>
   <td>Value i</td>
</tr>
<tr>
   <td>Label j</td>
   <td>Value j</td>
</tr>
<tr>
   <td>Label k</td>
   <td>Value k</td>
</tr>
<tr>
   <td>Label l</td>
   <td>Value l</td>
</tr>
<tr>
   <td>Label m</td>
   <td>Value m</td>
</tr>
<tr>
   <td>Label n</td>
   <td>Value n</td>
</tr>
<tr>
   <td>Label o</td>
   <td>Value o</td>
</tr>
<tr>
   <td>Label p</td>
   <td>Value p</td>
</tr>
<tr>
   <td>Label q</td>
   <td>Value q</td>
</tr>
<tr>
   <td>Label r</td>
   <td>Value r</td>
</tr>
<tr>
   <td>Label s</td>
   <td>Value s</td>
</tr>
<tr>
   <td>Label t</td>
   <td>Value t</td>
</tr>

<强>解释

  1. 使用标准XPath函数 name()starts-with()substring-after()

  2. 要显示的最大对数在名为pLimit的全局(外部)参数中提供。

  3. 解决方案的核心是将模板完全应用于我们要显示的Labelxx元素集。这些是深度为3的任何元素,其名称以字符串"label"开头,并且起始字符串"label"后面的名称的剩余部分是不大于指定限制的数字{{1 }}