Muhammad Hassan
Muhammad Hassan

Reputation: 505

XSLT Creating a variable to count number of iteration inside for-each

I don't know how can I create a variable and assi.

I'm new to using XSLT and I have an XML file that file have some nodes that nodes have some child I need to count those child using for-each (every for-each I need to increment that count by 1 and also my counter that I want start from 1)

I don't know how can I create an variable and assign it to value 1.

Here is example about what I need:

<root>
  <body>
    <sec id="sec1">
      <!--Parent also can contain no sub element or also can contain a free text-->
      <p></p>
      <p>some free text</p>
      <p>
        <!--Nodes I want to count it-->
        <childNodes></childNodes>
        <childNodes></childNodes>
        <childNodes></childNodes>
        <childNodes></childNodes>
        <childNodes></childNodes>
        <!--Nodes I want to count it-->
      </p>
    </sec>
    <sec id="sec2">
      <p>
        <!--Nodes I want to count it-->
        <childNodes></childNodes>
        <childNodes></childNodes>
        <childNodes></childNodes>
        <childNodes></childNodes>
        <childNodes></childNodes>
        <!--Nodes I want to count it-->
      </p>
      <p>
        <!--Nodes I want to count it-->
        <childNodes></childNodes>
        <childNodes></childNodes>
        <childNodes></childNodes>
        <childNodes></childNodes>
        <childNodes></childNodes>
        <!--Nodes I want to count it-->
      </p>
    </sec>
  </body>
</root>

The output I need like that

<root>
    <childNodes>
        <count> 
            The count of all childNodes
        </count>
    </childNodes>
</root>

Can you help to solve that problem, thanks in advance

Upvotes: 0

Views: 1270

Answers (2)

Aniket V
Aniket V

Reputation: 3247

Based on the shared output XML, there are 2 possible output options. Either get the total count of <childNodes> in the XML or get separate counts for p/childNodes.

Total count of <childNodes> can be fetched using below template

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > 
    <xsl:output method="xml" />
    <xsl:strip-space elements="*" />

    <xsl:template match="root">
        <xsl:copy>
            <childNodes>
                <count><xsl:value-of select="count(//childNodes)" /></count>
            </childNodes>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Output

<root>
    <childNodes>
        <count>15</count>
    </childNodes>
</root>

If you need separate counts

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > 
    <xsl:output method="xml" />
    <xsl:strip-space elements="*" />

    <xsl:template match="root">
        <xsl:copy>
            <xsl:apply-templates />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="p">
        <xsl:if test="*">
            <childNodes>
                <count><xsl:value-of select="count(*)" /></count>
            </childNodes>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Output

<root>
    <childNodes>
        <count>5</count>
    </childNodes>
    <childNodes>
        <count>5</count>
    </childNodes>
    <childNodes>
        <count>5</count>
    </childNodes>
</root>

Upvotes: 0

jdweng
jdweng

Reputation: 34421

Using xml linq :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication58
{
    class Program
    {
        static void Main(string[] args)
        {
            XElement root = new XElement("root");
            XElement body = new XElement("body");
            root.Add(body);


            for (int id = 1; id <= 10; id++)
            {
                XElement newSec = new XElement("sec",
                    new XAttribute("id", "sec" + id.ToString()),
                    XElement.Parse("<!--Parent also can contain no sub element or also can contain a free text--><p></p>"),
                    new XElement("p", "some free text")
                    );
                body.Add(newSec);
                XElement nodes = new XElement("p");
                newSec.Add(nodes);

                for (int childCount = 1; childCount <= 10; childCount++)
                {
                    XElement newChild = new XElement("childNods", new XAttribute("id", "node" + childCount.ToString()),
                        "Child Text"
                     );
                    nodes.Add(newChild);

                }

            }


        }

    }
}

Upvotes: 0

Related Questions