Venkata Penumatsa
Venkata Penumatsa

Reputation: 411

Populate footer row with the count of individual xml fields in XSLT

I am working on a requirement where I need to populate my footer line with the count of each XML fields present in my source XML. In the below sample XML there are total 4 <Report_Entry> are there. Inside every <Report_Entry> individual XML fields are there. I need to count all the fields inside each <Report_Entry> and put that count in the footer of the output.

I am able to achieve this by counting each sub XML field. Is this the right way to do it? Or any other better way to achieve this? Can you please advise?

<xsl:value-of select="sum(count(Report_Entry/id) + count(Report_Entry/name) + count(Report_Entry/bu) 
+ count(Report_Entry/dept))"/>

Sample XML

<?xml version='1.0' encoding='UTF-8'?>
<Report_Data>
    <Report_Entry>
        <id>12345</id>
        <name>john</name>
        <bu>1234</bu>
        <dept>IT</dept>
    </Report_Entry>
    <Report_Entry>
        <id>12346</id>
        <name>john</name>
        <bu>1294</bu>
    </Report_Entry>
    <Report_Entry>
        <id>12349</id>
        <dept>IT</dept>
    </Report_Entry>
    <Report_Entry>
        <id>12341</id>
        <name>john</name>
        <bu>1034</bu>
        <dept>IT</dept>
    </Report_Entry>
</Report_Data>

My XSLT

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0">

<xsl:output method="text" omit-xml-declaration="yes"/>

<xsl:variable name="tilde">
    <xsl:text>~</xsl:text>
</xsl:variable>
<xsl:variable name="nextline">
    <xsl:text>&#xA;</xsl:text>
</xsl:variable>


<xsl:template match="/Report_Data">

    <xsl:for-each select="Report_Entry">
        <xsl:if test="id">
            <xsl:value-of select="id"/>
            <xsl:value-of select="$tilde"/>
        </xsl:if>
        <xsl:if test="name">
            <xsl:value-of select="name"/>
            <xsl:value-of select="$tilde"/>
        </xsl:if>
        <xsl:if test="bu">
            <xsl:value-of select="bu"/>
            <xsl:value-of select="$tilde"/>
        </xsl:if>
        <xsl:if test="dept">
            <xsl:value-of select="dept"/>
            <xsl:value-of select="$tilde"/>
        </xsl:if>
        <xsl:value-of select="$nextline"/>
    </xsl:for-each>

    <xsl:value-of
        select="sum(count(Report_Entry/id) + count(Report_Entry/name) + count(Report_Entry/bu) + count(Report_Entry/dept))"/>


</xsl:template>
</xsl:stylesheet>

Output

12345~john~1234~IT~
12346~john~1294~
12349~IT~
12341~john~1034~IT~
13

Thanks In advance Venk

Upvotes: 0

Views: 303

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116982

Why not simply:

<xsl:value-of select="count(Report_Entry/*)"/>

Or, if you want to limit the count to known nodes only:

<xsl:value-of select="count(Report_Entry/(id, name, bu, dept))"/>

And while you're at it, you could shorten the whole thing to:

XSLT 2.0

<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>

<xsl:template match="/Report_Data">
    <xsl:for-each select="Report_Entry">
        <xsl:value-of select="id, name, bu, dept" separator="'~'"/>
        <xsl:text>&#xA;</xsl:text> 
    </xsl:for-each>
    <xsl:value-of select="count(Report_Entry/*)"/>
</xsl:template>

</xsl:stylesheet>

Upvotes: 2

Related Questions