<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:output indent="yes"/>
	<!-- multilevel grouping using the Muench method -->
	
	<!-- Establish a key for each grouping level.  Note that each lower level key value -->
	<!-- must include the key value of the higher order key -->
	<xsl:key name="kFamily" match="item" use="Family"/>
	<xsl:key name="kVernacularNameOfFamily" match="item" use="VernacularNameOfFamily"/>
	<xsl:key name="kSubfamily" match="item" use="concat(Family,':',Subfamily)"/>
	<xsl:key name="kGenus" match="item" use="concat(Family,':',Subfamily,':',Genus)"/>
	
	<xsl:template match="/">
		<html>
			<head>
				<title>Chrysidoidea</title>
				<link rel="stylesheet" type="text/css" href="chrysidoidea.css" title="default"/>
			</head>
			<body>
				<h1 class="superfamily">
					<xsl:value-of select="local-name(/*[1])"/>
				</h1>
				<!-- the outer for-each iterates once for each unique value of Family -->
				<xsl:for-each select="/*/item[generate-id()=generate-id(key('kFamily', Family)[1])]">
					<h2>
						<span class="Family">
							<xsl:value-of select="Family"/>
						</span>
						<span class="VernacularNameOfFamily">
							<xsl:value-of select="VernacularNameOfFamily"/>
						</span>
					</h2>
					
					<!-- this for-each iterates over the <item> nodes, once for each unique value of Subfamily -->
						<!-- that have the same value of Family as the containing for-each iteration -->
						<xsl:for-each select="key('kFamily', Family)[generate-id()=generate-id(key('kSubfamily',concat(Family,':',Subfamily))[1])]">
							<xsl:if test="string-length(Subfamily) &gt; 0">
								<h3 class="Subfamily">
									<xsl:value-of select="Subfamily"/>
								</h3>
							</xsl:if>
							<!-- this for-each iterates over the <item> nodes, once for each unique value of Genus -->
								<!-- that have the same value of Family and Subfamily as the containing for-each iteration -->
								<xsl:for-each select="key('kSubfamily',concat(Family,':',Subfamily))[generate-id()=generate-id(key('kGenus',concat(Family,':',Subfamily,':',Genus))[1])]">
									<xsl:if test="string-length(Genus) &gt; 0">
										<h4>
										<span class="Genus">
										<xsl:value-of select="Genus"/>
									</span>
									<span class="AuthorYearOfGenus">
										<xsl:value-of select="AuthorYearOfGenus"/>
									</span>
									<span class="VernacularNameOfGenus">
										<xsl:value-of select="VernacularNameOfGenus"/>
									</span>
								</h4>
							</xsl:if>
							<xsl:if test="count(*[(substring-before(local-name(),'_') = 'SynonymOfGenus') and (string-length() &gt; 0)]) &gt; 0">
								<ul class="SynGen">
									<xsl:for-each select="*[(substring-before(local-name(),'_') = 'SynonymOfGenus') and (string-length() &gt; 0)]">
										<xsl:variable name="localNameModifier" select="substring-after(local-name(.),'SynonymOfGenus')"/>
										<xsl:variable name="authorElementName" select="concat('AuthorYearOfSynonymOfGenus',$localNameModifier)"/>
										<li class="nodot">
										<span class="{local-name(.)}">
										<xsl:value-of select="."/>
									</span>
									<span>
										<xsl:attribute name="class">
										<xsl:value-of select="$authorElementName"/>
									</xsl:attribute>
									<xsl:value-of select="../*[local-name() = $authorElementName]"/>
								</span>
							</li>
						</xsl:for-each>
					</ul>
				</xsl:if>
				
				<ul class="SciName">
					<!-- this for-each iterates once for each <item> node -->
						<!-- that has the same value of Family, Subfamily, and Genus as the -->
						<!-- containing for-each iteration -->
						<xsl:for-each select="key('kGenus',concat(Family,':',Subfamily,':',Genus))">
							<!-- this for-each iterates over all the <ScientificName> nodes in the <item> -->
									<li>
										<xsl:for-each select="ScientificName">
										<xsl:variable name="myPosition" select="position()"/>
										<xsl:call-template name="outputDataAuthor">
										<xsl:with-param name="dataString">
										<xsl:value-of select="."/>
									</xsl:with-param>
									<xsl:with-param name="authorString">
										<xsl:value-of select="following-sibling::AuthorYearOfScientificName[$myPosition]"/>
									</xsl:with-param>
									<xsl:with-param name="className" select="'ScientificName'"/>
								</xsl:call-template>
							</xsl:for-each>

<xsl:if test="string-length(concat(InfraspecificRank_1, SynonymOfScientificName_1, QestionableSynonym)) &gt; 0">
  <ul class="SynSciName">

							<xsl:if test="count(QestionableSynonym) != 0">
								
									<xsl:for-each select="QestionableSynonym">
										<xsl:variable name="myPosition" select="position()"/>
										<xsl:call-template name="outputDataAuthor">
										<xsl:with-param name="dataString">
										<xsl:value-of select="."/>
									</xsl:with-param>
									<xsl:with-param name="authorString">
										<xsl:value-of select="following-sibling::AuthorYearOfQestionableSynonym[$myPosition]"/>
									</xsl:with-param>
									<xsl:with-param name="className" select="'QestionableSynonym'"/>
								</xsl:call-template>
							</xsl:for-each>
					</xsl:if>
					
					<xsl:for-each select="*[(substring-before(local-name(),'_') = 'SynonymOfScientificName') and (string-length() &gt; 0)]">
						<xsl:variable name="localNameModifier" select="substring-after(local-name(.),'SynonymOfScientificName')"/>
						<xsl:variable name="authorElementName" select="concat('AuthorYearOfSynonymOfScientificName',$localNameModifier)"/>
						<xsl:call-template name="outputDataAuthor">
							<xsl:with-param name="dataString">
								<xsl:value-of select="."/>
							</xsl:with-param>
							<xsl:with-param name="authorString">
								<xsl:value-of select="../*[local-name() = $authorElementName]"/>
							</xsl:with-param>
							<xsl:with-param name="className" select="local-name(.)"/>
						</xsl:call-template>
					</xsl:for-each>
					
					<xsl:for-each select="*[substring-before(local-name(),'_') = 'InfraspecificRank' and string-length(text()) &gt; 0]">
							<xsl:variable name="localNameModifier" select="substring-after(local-name(.),'InfraspecificRank')"/>
							<xsl:variable name="epithetName" select="concat('InfraspecificEpithet',$localNameModifier)"/>
							<xsl:variable name="epithetAuthorName" select="concat('AuthorYearOfInfraspecificEpithet',$localNameModifier)"/>
							<xsl:variable name="synName" select="concat('SynonymOfInfraspecificEpithet',$localNameModifier)"/>
							<xsl:variable name="synAuthorName" select="concat('AuthorYearOfSynonymOfInfraspecificEpithet',$localNameModifier)"/>
							<xsl:call-template name="outputRankEpithetAuthor">
								<xsl:with-param name="rankString">
									<xsl:value-of select="."/>
								</xsl:with-param>
								<xsl:with-param name="epithetString">
									<xsl:value-of select="../*[local-name() = $epithetName]"/>
								</xsl:with-param>
								<xsl:with-param name="authorString">
									<xsl:value-of select="../*[local-name() = $epithetAuthorName]"/>
								</xsl:with-param>
								<xsl:with-param name="rankClassName" select="local-name(.)"/>
								<xsl:with-param name="epithetClassName" select="$epithetName"/>
							</xsl:call-template>
							<xsl:call-template name="outputDataAuthor">
								<xsl:with-param name="dataString">
									<xsl:value-of select="./*[local-name() = $synName]"/>
								</xsl:with-param>
								<xsl:with-param name="authorString">
									<xsl:value-of select="./*[local-name() = $synAuthorName]"/>
								</xsl:with-param>
								<xsl:with-param name="className" select="$synName"/>
							</xsl:call-template>
					</xsl:for-each>
  </ul>
</xsl:if>
				</li>
			</xsl:for-each>
		</ul>
	</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</body>
</html>
</xsl:template>

<xsl:template name="outputDataAuthor">
	<xsl:param name="dataString"/>
	<xsl:param name="authorString"/>
	<xsl:param name="className"/>
	<xsl:if test="string-length($dataString) &gt; 0">
                <li class="inline">		
                <span class="{$className}">
			<xsl:value-of select="$dataString"/>
		</span>
                </li>

		<xsl:if test="string-length($authorString) &gt; 0">
                <li class="inline">	
			<span class="{concat('AuthorYearOf',$className)}">
				<xsl:value-of select="$authorString"/>
	                </span>

                </li>
                <br />
		</xsl:if>
	</xsl:if>
</xsl:template>

<xsl:template name="outputRankEpithetAuthor">
	<xsl:param name="rankString"/>
	<xsl:param name="epithetString"/>
	<xsl:param name="authorString"/>
	<xsl:param name="rankClassName"/>
	<xsl:param name="epithetClassName"/>
	<xsl:if test="string-length($rankString) &gt; 0">
                <li class="inline">
		<span class="{$rankClassName}">
			<xsl:value-of select="$rankString"/>
		</span>
                </li>
		<xsl:if test="string-length($epithetString) &gt; 0">
                <li class="inline">
			<span class="{$epithetClassName}">
				<xsl:value-of select="$epithetString"/>
			</span>
                </li>
		</xsl:if>
		<xsl:if test="string-length($authorString) &gt; 0">
                <li class="inline">
			<span class="{concat('AuthorYearOf',$epithetClassName)}">
				<xsl:value-of select="$authorString"/>
			</span>

                </li>
                <br />
		</xsl:if>
	</xsl:if>
</xsl:template>
</xsl:stylesheet>