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

Subject: [xsl] Issues using keys to find distinct parent and children
From: "Kamlesh Bafna" <Kamlesh.Bafna@xxxxxxxx>
Date: Wed, 27 May 2009 13:22:04 +0530
Hi All,

I am trying to use key in order to find the distinct parents & their
children. My input xml has the following hierarchy -
ProjectType
	Project
		Task

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.

I am using .NET & xslt 1.0.

My input xml is -
<?xml version="1.0" encoding="utf-8"?>
<tnsa:Projects xmlns:tns="http://local/Schema/Finance/Common/1.0";
xmlns:tnsa="http://local/Schema/Finance/ChargeableProject/1.0";>
	<tnsa:Project>
		<tns:ProjectType>Resources</tns:ProjectType>
		<tns:ProjectNumber>JXCS08015</tns:ProjectNumber>
		<tns:Task>
			<tns:TaskNumber>01</tns:TaskNumber>
		</tns:Task>
		<tns:Task>
			<tns:TaskNumber>01A</tns:TaskNumber>
		</tns:Task>
		<tns:Task>
			<tns:TaskNumber>01A-00</tns:TaskNumber>
		</tns:Task>
		<tns:Task>
			<tns:TaskNumber>01B</tns:TaskNumber>
		</tns:Task>
	</tnsa:Project>
	<tnsa:Project>
		<tns:ProjectType>Resources</tns:ProjectType>
		<tns:ProjectNumber>JXCS08015</tns:ProjectNumber>
		<tns:Task>
			<tns:TaskNumber>02</tns:TaskNumber>
		</tns:Task>
		<tns:Task>
			<tns:TaskNumber>02A</tns:TaskNumber>
		</tns:Task>
		<tns:Task>
			<tns:TaskNumber>01A-00</tns:TaskNumber>
		</tns:Task>
		<tns:Task>
			<tns:TaskNumber>01B</tns:TaskNumber>
		</tns:Task>
	</tnsa:Project>
	<tnsa:Project>
		<tns:ProjectType>GI</tns:ProjectType>
		<tns:ProjectNumber>GI000054</tns:ProjectNumber>
		<tns:Task>
			<tns:TaskNumber>5</tns:TaskNumber>
		</tns:Task>
		<tns:Task>
			<tns:TaskNumber>5.1</tns:TaskNumber>
		</tns:Task>
		<tns:Task>
			<tns:TaskNumber>5.1.1</tns:TaskNumber>
		</tns:Task>
	</tnsa:Project>
</tnsa:Projects>

I am using the following xslt -
<?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: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)"/>

	<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))[generate-id() = generate-id(key('by-Task',
concat(tns:ProjectType, '|', tns:ProjectNumber, '|',
tns:Task/tns:TaskNumber))[1])]" mode="Task"/>
		</Project_Code>
	</xsl:template>

	<xsl:template match="tnsa:Project" mode="Task">

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

Actual Output - (Unique Task are missing and only the first task is
picked under the project)
<Message xmlns:tns="http://ref.itvplc.ads/Schema/Finance/Common/1.0";
xmlns:tnsa="http://ref.itvplc.ads/Schema/Finance/ChargeableProject/1.0";>
	<Project_Type>
		<Row>
			<Type>Project_Type</Type>
			<Code>Resources</Code>
		</Row>
		<Project_Code>
			<Row>

<ParentCodeType>Project_Type</ParentCodeType>
				<ParentCode>Resources</ParentCode>
				<Type>Project</Type>
				<Code>JXCS08015</Code>
			</Row>
			<Task>
				<Row>
					<Type>Task</Type>
					<Code>01</Code>
				</Row>
			</Task>
			<Task>
				<Row>
					<Type>Task</Type>
					<Code>02</Code>
				</Row>
			</Task>
		</Project_Code>
	</Project_Type>
	<Project_Type>
		<Row>
			<Type>Project_Type</Type>
			<Code>GI</Code>
		</Row>
		<Project_Code>
			<Row>

<ParentCodeType>Project_Type</ParentCodeType>
				<ParentCode>GI</ParentCode>
				<Type>Project</Type>
				<Code>GI000054</Code>
			</Row>
			<Task>
				<Row>
					<Type>Task</Type>
					<Code>5</Code>
				</Row>
			</Task>
		</Project_Code>
	</Project_Type>
</Message>

Expected output -
<Message xmlns:tns="http://ref.itvplc.ads/Schema/Finance/Common/1.0";
xmlns:tnsa="http://ref.itvplc.ads/Schema/Finance/ChargeableProject/1.0";>
	<Project_Type>
		<Row>
			<Type>Project_Type</Type>
			<Code>Resources</Code>
		</Row>
		<Project_Code>
			<Row>

<ParentCodeType>Project_Type</ParentCodeType>
				<ParentCode>Resources</ParentCode>
				<Type>Project</Type>
				<Code>JXCS08015</Code>
			</Row>
			<Task>
				<Row>
					<Type>Task</Type>
					<Code>01</Code>
				</Row>
			</Task>
			<Task>
				<Row>
					<Type>Task</Type>
					<Code>01A</Code>
				</Row>
			</Task>
			<Task>
				<Row>
					<Type>Task</Type>
					<Code>01A-00</Code>
				</Row>
			</Task>
			<Task>
				<Row>
					<Type>Task</Type>
					<Code>01B</Code>
				</Row>
			</Task>
			<Task>
				<Row>
					<Type>Task</Type>
					<Code>02</Code>
				</Row>
			</Task>
		</Project_Code>
	</Project_Type>
	<Project_Type>
		<Row>
			<Type>Project_Type</Type>
			<Code>GI</Code>
		</Row>
		<Project_Code>
			<Row>

<ParentCodeType>Project_Type</ParentCodeType>
				<ParentCode>GI</ParentCode>
				<Type>Project</Type>
				<Code>GI000054</Code>
			</Row>
			<Task>
				<Row>
					<Type>Task</Type>
					<Code>5</Code>
				</Row>
			</Task>
			<Task>
				<Row>
					<Type>Task</Type>
					<Code>5.1</Code>
				</Row>
			</Task>
			<Task>
				<Row>
					<Type>Task</Type>
					<Code>5.1.1</Code>
				</Row>
			</Task>

		</Project_Code>
	</Project_Type>
</Message>

Thanks
Kamlesh








The information contained in this communication is intended solely for
the use of the individual or entity to whom it is addressed and others
authorized to receive it.   It may contain confidential or legally
privileged information.   If you are not the intended recipient you are
hereby notified that any disclosure, copying, distribution or taking any
action in reliance on the contents of this information is strictly prohibited
and may be unlawful. If you have received this communication in error,
please notify us immediately by forwarding this email to
MailAdmin@xxxxxxxx and then delete it from your system.

Ness technologies is neither liable for the proper and complete
transmission of the information contained in this communication nor for
any delay in its receipt.

Current Thread