Re: [xsl] Issues using keys to find distinct parent and children

Subject: Re: [xsl] Issues using keys to find distinct parent and children
From: Martin Honnen <Martin.Honnen@xxxxxx>
Date: Wed, 27 May 2009 12:10:19 +0200
Kamlesh Bafna wrote:

My issue is that the xslt I have written picks the distinct project type
& projects properly. However it picks only the first distinct task under
various project but not all the distinct task. I am unable to find my
mistake in the code.


<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";

xmlns:tns="http://local/Schema/Finance/Common/1.0";
xmlns:tnsa="http://local/Schema/Finance/ChargeableProject/1.0";>


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

	<xsl:key name="by-ProjectType"
             match="tnsa:Project"
             use="tns:ProjectType"/>

	<xsl:key name="by-ProjectNumber"
             match="tnsa:Project"
             use="concat(tns:ProjectType, '|', tns:ProjectNumber)"/>

	<xsl:key name="by-Task"
			match="tnsa:Project"
			use="concat(tns:ProjectType, '|',
tns:ProjectNumber, '|', tns:Task/tns:TaskNumber)"/>

You need to change that key to match the tns:Task element, as in the following stylesheet:


<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
	
xmlns:tns="http://local/Schema/Finance/Common/1.0";
	
xmlns:tnsa="http://local/Schema/Finance/ChargeableProject/1.0";>

<xsl:output indent="yes"/>

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

	<xsl:key name="by-ProjectType"
             match="tnsa:Project"
             use="tns:ProjectType"/>

	<xsl:key name="by-ProjectNumber"
             match="tnsa:Project"
             use="concat(tns:ProjectType, '|', tns:ProjectNumber)"/>

<xsl:key name="by-Task"
match="tns:Task"
use="concat(parent::tnsa:Project/tns:ProjectType, '|', parent::tnsa:Project/tns:ProjectNumber, '|', tns:TaskNumber)"/>


	<xsl:template match="tnsa:Projects">
		<xsl:apply-templates select="tnsa:Project[generate-id()
= generate-id(key('by-ProjectType', tns:ProjectType)[1])]"
mode="tns:ProjectType"/>
	</xsl:template>

	<xsl:template match="tnsa:Project" mode="tns:ProjectType">
		<Project_Type>
			<Row>
				<Type>
					<xsl:value-of
select="'Project_Type'"/>
				</Type>
				<Code>
					<xsl:value-of
select="tns:ProjectType"/>
				</Code>
			</Row>
			<xsl:apply-templates
select="key('by-ProjectType',tns:ProjectType)[generate-id() =
generate-id(key('by-ProjectNumber', concat(tns:ProjectType, '|',
tns:ProjectNumber))[1])]" mode="tns:ProjectNumber"/>
		</Project_Type>
	</xsl:template>

<xsl:template match="tnsa:Project" mode="tns:ProjectNumber">
<Project_Code>
<Row>
<ParentCodeType>
<xsl:value-of
select="'Project_Type'"/>
</ParentCodeType>
<ParentCode>
<xsl:value-of
select="./tns:ProjectType"/>
</ParentCode>
<Type>
<xsl:value-of
select="'Project'"/>
</Type>
<Code>
<xsl:value-of
select="tns:ProjectNumber"/>
</Code>
</Row>
<xsl:apply-templates
select="key('by-ProjectNumber', concat(tns:ProjectType, '|',
tns:ProjectNumber))/tns:Task[generate-id() = generate-id(key('by-Task',
concat(parent::tnsa:Project/tns:ProjectType, '|', parent::tnsa:Project/tns:ProjectNumber, '|', tns:TaskNumber))[1])]" />
</Project_Code>
</xsl:template>


<xsl:template match="tns:Task">

		<!--Task Identification-->
			<Task>
				<Row>
					<Type>
						<xsl:value-of
select="'Task'"/>
					</Type>
					<Code>
						<xsl:value-of
select="tns:TaskNumber"/>
					</Code>
				</Row>
			</Task>
	</xsl:template>
</xsl:stylesheet>

That way you can process distinct tasks.

--

	Martin Honnen
	http://msmvps.com/blogs/martin_honnen/

Current Thread