[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message] RE: creating a head-letter for directory
Hi Dorothy, Based on the input file you gave... the xslt below will do exactly what you want: <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:template match="/"> <xsl:apply-templates/> </xsl:template> <xsl:template match="root"> <output> <xsl:for-each-group select="data" group-by="substring(name, 1,1)"> <letter><xsl:value-of select="current-grouping-key()"/></letter> <xsl:for-each select="current-group()"> <name> <xsl:value-of select="name"/> </name> </xsl:for-each> </xsl:for-each-group> </output> </xsl:template> <!-- copy all nodes and attributes which are not processed by one of available templates --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:apply-templates/> </xsl:copy> </xsl:template> </xsl:stylesheet> Cheers, Robby Pelssers -----Original Message----- From: Hoskins & Gretton [mailto:hoskgret@xxxxxxxxxxxxxxxx] Sent: Monday, January 18, 2010 6:07 AM To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx Subject: creating a head-letter for directory HI, I would like to understand, given a flat sort of data extraction, of the type <?xml version="1.0" encoding="UTF-8"?> <root> <data> <name>Aname</name> <!-- other elements such as <location> follow, all related to the <name> --> </data> <data> <name>Hname</name><!-- other elements such as <location> follow --> </data> <data> <name>Dname</name><!-- other elements such as <location> follow --> </data> <data> <name>Wname</name><!-- other elements such as <location> follow --> </data> <data> <name>Anothername</name><!-- other elements such as <location> follow --> </data> <data> <name>Whatevername</name><!-- other elements such as <location> follow --> </data> </root> what are the groupings and keys needed to accomplish this (even flatter) output? <output> <letter>A</etter> <name>Aname</name><!-- other elements such as <location> follow --> <name>Anothername</name><!-- other elements such as <location> follow --> <letter>D</etter> <name>Dname</name><!-- other elements such as <location> follow --> <letter>H</etter> <name>Hname</name><!-- other elements such as <location> follow --> <letter>W</etter> <name>Wname</name><!-- other elements such as <location> follow --> <name>Whatevername</name><!-- other elements such as <location> follow --> <output> I know that I first need to identify which first letters exist in the set of <data> elements, and then generate a <letter> element containing that first letter, followed by all the data elements children <name> that have a matching first letter. But I'm getting a <letter> element every time, rather than once for each unique occurrence, followed by the <name> elements which have a matching first letter. How do I generate the <letter> once, but follow it with all of the <name> (and related) elements? I think I need to move the <leter> element builder up out of the for-each loop that it is in, but I don't know how I then would get each letter only once for the set of all <data> elements. <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> <xsl:template match="/"> <xsl:variable name="blocks" select="root/data"/> <xsl:element name="output"> <xsl:for-each-group select="$blocks" group-by="name"> <xsl:sort select="current-grouping-key()"/> <xsl:variable name="currentGroup" select="current-grouping-key()"/> <xsl:variable name="headletter" select="substring($currentGroup,1,1)"/> <xsl:for-each select="."><!-- context here should be data --> <xsl:element name="letter"> <xsl:value-of select="$headletter"/> </xsl:element> <xsl:apply-templates select="name[substring(.,1,1)=$headletter]"></xsl:apply-templates> </xsl:for-each> </xsl:for-each-group> </xsl:element> </xsl:template> <xsl:template match="name"> <!-- is there a way that I should use the $headletter here? --> <xsl:element name="name"><xsl:value-of select="."/></xsl:element> </xsl:template> </xsl:stylesheet> output with duplicate <letter> values: <?xml version="1.0" encoding="UTF-8"?> <output> <letter>A</letter> <name>Aname</name> <letter>A</letter> <name>Anothername</name> <letter>D</letter> <name>Dname</name> <letter>H</letter> <name>Hname</name> <letter>W</letter> <name>Whatevername</name> <letter>W</letter> <name>Wname</name> </output> Regards, Dorothy
|
PURCHASE STYLUS STUDIO ONLINE TODAY!Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced! Download The World's Best XML IDE!Accelerate XML development with our award-winning XML IDE - Download a free trial today! Subscribe in XML format
|