Search code examples
xmlxsltxslt-2.0

How to count number of nodes in XSLT with various conditions


I have XML, based on which I am creating a text file output. In the trailer record I have to count the total number of records in the output file. The logic used to create output file from XML is if the PreTaxAmt,or MatchAmt, or RothAmt for each report entry has a value greater than zero, there is one line created in output. If the Loanamt is greater than zero for each report entry then the record is outputted in a separate line. Please suggest me how can I use the count function to create the total counts of the line in the XSLT. I am pasting below what I have tried.

< Report_Entry>
    < Participant_ID>033709571</ Participant_ID>
    < Workers>
        < FULL_PART_Time_Indicator>1</ FULL_PART_Time_Indicator>
        < Last_Name>Vani</ Last_Name>
        < First_Name>Mehul</ First_Name>
        < Middle_Name>N</ Middle_Name>
        < Rehire_Date_1>2013-04-15-07:00</ Rehire_Date_1>
    </ Workers>
    < End_Date_from_Pay_Period>2016-01-03-08:00</ End_Date_from_Pay_Period>
    < PreTaxAmt>100.8</ PreTaxAmt>
    < MatchAmt>100.8</ MatchAmt>
    < RothAmt>0</ RothAmt>
    < LoanAmt>80</ LoanAmt>
</ Report_Entry>
< Report_Entry>
    < Participant_ID>037686040</ Participant_ID>
    < Workers>
        < FULL_PART_Time_Indicator>1</ FULL_PART_Time_Indicator>
        < Last_Name>Phonevilay</ Last_Name>
        < First_Name>Somsaath</ First_Name>
        < Gender_Code>1</ Gender_Code>
        < Rehire_Date_1>2012-06-18-07:00</ Rehire_Date_1>
    </ Workers>
    < End_Date_from_Pay_Period>2016-01-03-08:00</ End_Date_from_Pay_Period>
    < PreTaxAmt>61.81</ PreTaxAmt>
    < MatchAmt>61.81</ MatchAmt>
    < RothAmt>0</ RothAmt>
    < LoanAmt>76</ LoanAmt>
</ Report_Entry>
< Report_Entry>
    < Participant_ID>043781931</ Participant_ID>
    < Workers>
        < FULL_PART_Time_Indicator>1</ FULL_PART_Time_Indicator>
        < Last_Name>Ousouphan</ Last_Name>
        < First_Name>Phouangmala</ First_Name>
        < Gender_Code>2</ Gender_Code>
        < Rehire_Date_1>2001-03-20-08:00</ Rehire_Date_1>
    </ Workers>
    < End_Date_from_Pay_Period>2016-01-03-08:00</ End_Date_from_Pay_Period>
    < PreTaxAmt>84.19</ PreTaxAmt>
    < MatchAmt>0</ MatchAmt>
    < RothAmt>75</ RothAmt>
    < LoanAmt>90</ LoanAmt>
</ Report_Entry>

The XSLT code that I have used is below and it should output 6.

<xsl:if test="( PreTaxAmt != 0) or( MatchAmt != 0) or ( RothAmt != 0) ">
        <xsl:variable name="recordCount">
        <xsl:value-of select=" 
            count( Report_Data/ Report_Entry/ PreTaxAmt) 
            "/>
        </xsl:variable>
    </xsl:if>
            <xsl:if  test=" LoanAmt != 0"> 
                <xsl:variable name="recordCount1">
                    <xsl:value-of select=" 
                        count( Report_Data/ Report_Entry/ LoanAmt) 
                        "/>

                </xsl:variable>
                <xsl:variable name="var3" select="number($recordCount) + number($recordCount1)"/>
            </xsl:if>

Solution

  • Assuming that you repair your text object to be well-formed XML by

    • removing all spaces from the tag names
    • adding a Report_Data root element

    as follows:

    <Report_Data>
      <Report_Entry>
        <Participant_ID>033709571</Participant_ID>
        <Workers>
          <FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
          <Last_Name>Vani</Last_Name>
          <First_Name>Mehul</First_Name>
          <Middle_Name>N</Middle_Name>
          <Rehire_Date_1>2013-04-15-07:00</Rehire_Date_1>
        </Workers>
        <End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
        <PreTaxAmt>100.8</PreTaxAmt>
        <MatchAmt>100.8</MatchAmt>
        <RothAmt>0</RothAmt>
        <LoanAmt>80</LoanAmt>
      </Report_Entry>
      <Report_Entry>
        <Participant_ID>037686040</Participant_ID>
        <Workers>
          <FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
          <Last_Name>Phonevilay</Last_Name>
          <First_Name>Somsaath</First_Name>
          <Gender_Code>1</Gender_Code>
          <Rehire_Date_1>2012-06-18-07:00</Rehire_Date_1>
        </Workers>
        <End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
        <PreTaxAmt>61.81</PreTaxAmt>
        <MatchAmt>61.81</MatchAmt>
        <RothAmt>0</RothAmt>
        <LoanAmt>76</LoanAmt>
      </Report_Entry>
      <Report_Entry>
        <Participant_ID>043781931</Participant_ID>
        <Workers>
          <FULL_PART_Time_Indicator>1</FULL_PART_Time_Indicator>
          <Last_Name>Ousouphan</Last_Name>
          <First_Name>Phouangmala</First_Name>
          <Gender_Code>2</Gender_Code>
          <Rehire_Date_1>2001-03-20-08:00</Rehire_Date_1>
        </Workers>
        <End_Date_from_Pay_Period>2016-01-03-08:00</End_Date_from_Pay_Period>
        <PreTaxAmt>84.19</PreTaxAmt>
        <MatchAmt>0</MatchAmt>
        <RothAmt>75</RothAmt>
        <LoanAmt>90</LoanAmt>
      </Report_Entry>
    </Report_Data>
    

    Then the following XSLT,

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0"
                    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
      <xsl:output method="text"/>
    
      <xsl:template match="/Report_Data">
        <xsl:value-of select="count(Report_Entry[   number(PreTaxAmt) > 0
                                                 or number(MatchAmt) > 0
                                                 or number(RothAmt) > 0])
                              + count(Report_Entry[number(LoanAmt) > 0])"/>
      </xsl:template>
    
    </xsl:stylesheet>
    

    Will output 6 as requested.