#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    2
    Rep Power
    0

    Count how many nodes have the same value of a child node (with xslt using variables)


    Hello,
    I'd like to Count how many nodes have the same value of a child node and display the list(with xslt using variables)

    The xml is smth like this:

    Code:
    <list>
    <student>
    	<name>Student1</name>
    	<major>Chemistry</major>
    	<email>st1@example.com</email>
    </student>
    <student>
    	<name>Student2</name>
    	<major>Chemistry</major>
    	<email>st2@example.com</email>
    </student>
    <student>
    	<name>Student3</name>
    	<major>Engineering</major>
    	<email>st3@example.com</email>
    </student>
    </list>
    I want to count how many students are at every major and display the list, so smth like this:

    Chemistry - 2
    Student1
    Student2
    Engineering - 1
    Student3
    ...
  2. #2
  3. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2006
    Posts
    24
    Rep Power
    0
    xslt 2.0 for-each-group is best for this

    input.xml

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <list>
      <student>
        <name>Student1</name>
        <major>Chemistry</major>
        <email>st1@example.com</email>
      </student>
      <student>
        <name>Student2</name>
        <major>Chemistry</major>
        <email>st2@example.com</email>
      </student>
      <student>
        <name>Student3</name>
        <major>Engineering</major>
        <email>st3@example.com</email>
      </student>
    </list>
    xsl

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    
    	<xsl:output method="xml" indent="yes"/>
    
    	<xsl:template match="/">
        <xsl:element name="root">
          <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    	</xsl:template>
    	
    	<xsl:template match="text()|@*"/>
    
    	<xsl:template match="list">
          <xsl:for-each-group select="student" group-by="descendant::major">
            <xsl:element name="{major/text()}">
              <xsl:attribute name="num-students" select="count(current-group())"/>
              <xsl:for-each select="current-group()">
                <xsl:copy-of select="."/>
              </xsl:for-each>
            </xsl:element>
          </xsl:for-each-group>
    	</xsl:template>
    
    </xsl:stylesheet>
    result
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <root>
    	<Chemistry num-students="2">
    		<student>
    			<name>Student1</name>
    			<major>Chemistry</major>
    			<email>st1@example.com</email>
    		</student>
    		<student>
    			<name>Student2</name>
    			<major>Chemistry</major>
    			<email>st2@example.com</email>
    		</student>
    	</Chemistry>
    	<Engineering num-students="1">
    		<student>
    			<name>Student3</name>
    			<major>Engineering</major>
    			<email>st3@example.com</email>
    		</student>
    	</Engineering>
    </root>
    xsl for txt ouput instead
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions">
    
    	<xsl:output method="text"/>
    
    	<xsl:template match="/">
          <xsl:apply-templates select="node()|@*"/>
    	</xsl:template>
    	
    	<xsl:template match="text()|@*"/>
    
    	<xsl:template match="list">
          <xsl:for-each-group select="student" group-by="descendant::major">
            <xsl:value-of select="major/text()"/> - <xsl:value-of select="count(current-group())"/><xsl:text>&#xd;</xsl:text>
              <xsl:for-each select="current-group()">
                <xsl:value-of select="name"/>
                <xsl:text>&#xd;</xsl:text>
              </xsl:for-each>
          </xsl:for-each-group>
    	</xsl:template>
    
    </xsl:stylesheet>
    txt result

    Code:
    Chemistry - 2
    Student1
    Student2
    Engineering - 1
    Student3
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2006
    Posts
    24
    Rep Power
    0
    CODE tags are interpreting the nl entity in the xsl

    please add yourself

    <xsl:value-of select="major/text()"/> - <xsl:value-of select="count(current-group())"/><xsl:text>&amp;#xd;</xsl:text>
    <xsl:for-each select="current-group()">
    <xsl:value-of select="name"/>
    <xsl:text>&amp;#xd;</xsl:text>
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2013
    Posts
    2
    Rep Power
    0
    Thanks a lot, it works,
    but how could this be done in xslt 1.0 and using variables , I tried creating a variable to hold all the majors and going over each value with for-each, but I don't know how to count and skip the repeated ones , any suggestions would help me a lot
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2006
    Posts
    24
    Rep Power
    0
    Since you're stuck with xslt 1.0, please google "xslt muenchian" - it will work but learning curve is higher. Good Luck.

IMN logo majestic logo threadwatch logo seochat tools logo