Search code examples
xsltxslt-2.0

How to loop through a particular tag and display it row after row?


I am a beginner in XSLT. I am trying to create an AFP document using Apache FOP. I have an input XML like this:

<letter>
 <data>
   <product>
     <a>test</a>
     <b>test1</b>
     <product>
      <charge>
        <one-time-charge>
         <amount>30</amount>
         <info>MNO</info>
        </one-time-charge>
      </charge>
         <product>
          <charge>
           <one-time-charge>
            <amount>10</amount>
            <info>XYZ</info>
           </one-time-charge>
          </charge>
         </product>
         <product>
          <charge>
           <one-time-charge>
            <amount>20</amount>
            <info>ABC</info>
           </one-time-charge>
          </charge>
         </product>
     </product>
    </product>
    </data>
   </letter>

As u can see, there are 3 levels of "product" tag. The "product" tag levels can sometimes be 2 as well.

the expected output is as below:

MNO                                       30
XYZ                                       10
ABC                                       20

How do i loop through the "info" tag and "amount" tag irrespective of the level?

Update:

After using descendant axis :

I am able to get the values out of this code, but it does not add new row for each info

<xsl:for-each select="data/product/product"> 
 <fo:table-row> 
  <fo:table-cell> 
   <fo:block font-family="Arial" font-size="9pt" font-weight="normal"> 
 <xsl:value-of select="descendant::one-time-charge/info"/> 
 </fo:block> 
 </fo:table-cell> 
<fo:table-cell> 
   <fo:block font-family="Arial" font-size="9pt" font-weight="normal"> 
 <xsl:value-of select="descendant::one-time-charge/amount"/> 
 </fo:block> 
 </fo:table-cell>
 </fo:table-row> 
</xsl:for-each>
      

The output is as follows:

MNO XYZ ABC                          301020

Required:

MNO                               30
XYZ                               10
ABC                               20

Solution

  • To use the descendant axis as suggested, you should be doing something like:

    <xsl:template match="/">
        <table>
            <xsl:for-each select="//product/charge/one-time-charge"> 
                <row>
                    <cell>
                        <xsl:value-of select="info"/>
                    </cell> 
                    <cell>
                        <xsl:value-of select="amount"/>
                    </cell> 
                </row>
            </xsl:for-each>
        </table>
    </xsl:template>