循环中的 XSLT 动态节点名称

发布于 2024-12-03 23:54:12 字数 1622 浏览 0 评论 0原文

有谁知道是否可以循环遍历模板并根据迭代数提取节点值。例如,我有以下 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>

任何人都可以提出解决方案吗?

Does anyone know if it's possible to loop through a template and pull out node values based on an iterating number. So for example, I have the following XML strucutre:

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

There are always 20 label/value pairs of data. I want to output these via XSLT in a table. By looping through a template 20 times (unless there's a better way).

The code I have below works, but it won't accept a dynamic number when outputting the values (e.g.

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

)

Here's the code so far:

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

Can anyone suggest a solution to this?

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

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

发布评论

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

评论(2

清晰传感 2024-12-10 23:54:12
<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>
<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>

Output:

<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>
去了角落 2024-12-10 23:54:12

此转换

<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" 后面的名称的剩余部分是一个数字,不大于指定的限制$pLimit

This transformation:

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

when applied on this XML document (similar to the provided, but with 21 label-value pairs):

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

produces the wanted, correct result:

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

Explanation:

  1. Using the standard XPath functions name(), starts-with() and substring-after()

  2. The maximum number of pairs to display is provided in the global (external) parameter named pLimit.

  3. The core of the solution is applying templates exactly on the set of Labelxx elements that we want to display. These are any elements at depth 3 whose name starts with the string "label" and where the remaining part of the name that follows the starting string "label" is a number that is not greater than the specified limit $pLimit.

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