Dynamic XSLT node name in a loop

Does anyone know if it is possible to scroll the pattern and pull out the node values ​​based on the iteration number. So, for example, I have the following XML file:

<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 pairs of label / value data. I want to output them through XSLT in a table. By scrolling the template 20 times (if there is no better way).

The code that I have below works, but it does not accept a dynamic number when outputting values ​​(for example,

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

)

Here is the code:

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

Can anyone suggest a solution?

+4
source share
2 answers

 <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> 
+3
source

This conversion is :

 <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 to this XML document (similar to the one provided, but with 21 character 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> 

creates the desired, 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

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

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

  • The core of the solution is the application of templates specifically to the set of Labelxx elements that we want to display . These are any elements at depth 3 whose name begins with the string "label" , and the rest of the name that follows the initial string "label" is a number that does not exceed the specified limit of $pLimit .

+1
source