Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

XML transformation using XSLT - recursion 1

Status
Not open for further replies.

RemoteSilicon

Programmer
Feb 13, 2001
45
0
0
GB
I would like to transform some XML using XSLT that involves recursion.

The source XML format is:
<?xml version="1.0" encoding="ISO-8859-1"?>
<Products>
<Product Status="Updated" Type="Both">
<GUID>cca0c671-7070-411d-91e8-895361b53e19</GUID>
<ProductID>48936</ProductID>
<Description>Main Product 1</Description>
<Sequence>357</Sequence>
<LastModifiedTimeStamp>2013-06-06</LastModifiedTimeStamp>
<Parts>
<ProductPart PartType="Individual">
<Name>Individual Part 1-1</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>3</Quantity>
</ProductPart>
<ProductPart PartType="Individual">
<Name>Individual Part 1-2</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>1</Quantity>
</ProductPart>
<ProductPart PartType="SubProduct">
<Name>Sub Product 2</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>1</Quantity>
<SubParts>
<ProductPart PartType="Individual">
<Name>Individual Part 2-1</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>5</Quantity>
</ProductPart>
<ProductPart PartType="Individual">
<Name>Individual Part 2-2</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>10</Quantity>
</ProductPart>
<ProductPart PartType="SubProduct">
<Name>Sub Product 3</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>2</Quantity>
<SubParts>
<ProductPart PartType="Individual">
<Name>Individual Part 3-1</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>6</Quantity>
</ProductPart>
</SubParts>
</ProductPart>
</SubParts>
</ProductPart>
</Parts>
</Product>
</Products>

Target XML:
<Products>
<Product>
<GUID>cca0c671-7070-411d-91e8-895361b53e19</GUID>
<ProductID>48936</ProductID>
<Description>Main Product 1</Description>
<Sequence>357</Sequence>
<LastModifiedTimeStamp>2013-06-06</LastModifiedTimeStamp>
<Subproducts>
<ProductPart PartType="SubProduct">
<Name>Sub Product 2</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>1</Quantity>
<Subproducts>
<ProductPart PartType="SubProduct">
<Name>Sub Product 3</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>2</Quantity>
<Subproducts />
<Subparts>
<ProductPart PartType="Individual">
<Name>Individual Part 3-1</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>6</Quantity>
</ProductPart>
</Subparts>
</ProductPart>
</Subproducts>
<Subparts>
<ProductPart PartType="Individual">
<Name>Individual Part 2-1</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>5</Quantity>
</ProductPart>
<ProductPart PartType="Individual">
<Name>Individual Part 2-2</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>10</Quantity>
</ProductPart>
</Subparts>
</ProductPart>
</Subproducts>
<Subparts>
<ProductPart PartType="Individual">
<Name>Individual Part 1-1</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>3</Quantity>
</ProductPart>
<ProductPart PartType="Individual">
<Name>Individual Part 1-2</Name>
<GUID>a06ac00e-96ed-4c70-8040-6a280bfc8cf2</GUID>
<Quantity>1</Quantity>
</ProductPart>
</Subparts>
</Product>
</Products>

The XSLT I have written is as follows:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl=" xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="msxsl">

<xsl:template match='/Products'>
<Products>
<xsl:apply-templates select='Product'/>
</Products>
</xsl:template>

<xsl:template match='Product'>
<Product>
<GUID>
<xsl:value-of select='GUID'/>
</GUID>
<ProductID>
<xsl:value-of select='ProductID'/>
</ProductID>
<Description>
<xsl:value-of select='Description'/>
</Description>
<Sequence>
<xsl:value-of select='Sequence'/>
</Sequence>
<LastModifiedTimeStamp>
<xsl:value-of select='LastModifiedTimeStamp'/>
</LastModifiedTimeStamp>
<Subproducts>
<xsl:apply-templates select='Parts/ProductPart'>
<xsl:with-param name="SubPartParam" select="''" />
</xsl:apply-templates>
</Subproducts>
<Subparts>
<xsl:apply-templates select='Parts/ProductPart'>
<xsl:with-param name="SubPartParam" select="'Yes'" />
</xsl:apply-templates>
</Subparts>
</Product>
</xsl:template>

<xsl:template match='ProductPart'>
<xsl:param name="SubPartParam"/>

<xsl:choose>

<xsl:when test="($SubPartParam='' and @IngredientType='SubProduct')">
<ProductPart>
<xsl:attribute name='PartType'>
<xsl:value-of select='@PartType'/>
</xsl:attribute>
<xsl:apply-templates select='ProductPart' />
<Name>
<xsl:value-of select='Name'/>
</Name>
<GUID>
<xsl:value-of select='GUID'/>
</GUID>
<Quantity>
<xsl:value-of select='Quantity'/>
</Quantity>
</ProductPart>
</xsl:when>

<xsl:when test="($SubPartParam='Yes' and @IngredientType='Individual')">
<ProductPart>
<xsl:attribute name='PartType'>
<xsl:value-of select='@PartType'/>
</xsl:attribute>
<xsl:apply-templates select='ProductPart' />
<Name>
<xsl:value-of select='Name'/>
</Name>
<GUID>
<xsl:value-of select='GUID'/>
</GUID>
<Quantity>
<xsl:value-of select='Quantity'/>
</Quantity>
</ProductPart>
</xsl:when>

</xsl:choose>

</xsl:template>

</xsl:stylesheet>
Could someone please help me with the XSLT? I haven't done much work on XML transformation before and am in desperate need for help
 
Your XSLT showed that you need to study [highlight #8AE234]XPath predicates[/highlight] and [highlight #729FCF]Attribute Value Templates[/highlight].

I modified your style sheet as follows:
Code:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform"[/URL] xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:output indent="yes"/>

<xsl:template match="/Products">
	<Products>
		<xsl:apply-templates select="Product"/>
	</Products>
</xsl:template>

<xsl:template match="Product">
	<Product>
		<GUID>
			<xsl:value-of select="GUID"/>
		</GUID>
		<ProductID>
			<xsl:value-of select="ProductID"/>
		</ProductID>
		<Description>
			<xsl:value-of select="Description"/>
		</Description>
		<Sequence>
			<xsl:value-of select="Sequence"/>
		</Sequence>
		<LastModifiedTimeStamp>
			<xsl:value-of select="LastModifiedTimeStamp"/>
		</LastModifiedTimeStamp>
		<Subproducts>
			<xsl:apply-templates select="Parts/ProductPart[highlight #8AE234][@PartType='SubProduct'][/highlight]"/>
		</Subproducts>
		<Subparts>
			<xsl:apply-templates select="Parts/ProductPart[highlight #8AE234][@PartType!='SubProduct'][/highlight]"/>
		</Subparts>
	</Product>
</xsl:template>

<xsl:template match="ProductPart">
	<ProductPart PartType="[highlight #729FCF]{@PartType}[/highlight]">
		<Name>
			<xsl:value-of select="Name"/>
		</Name>
		<GUID>
			<xsl:value-of select="GUID"/>
		</GUID>
		<Quantity>
			<xsl:value-of select="Quantity"/>
		</Quantity>
		<xsl:if test="SubParts/ProductPart[@PartType='SubProduct']">
		<Subproducts>
			<xsl:apply-templates select="SubParts/ProductPart[highlight #8AE234][@PartType='SubProduct'][/highlight]"/>
		</Subproducts>
		</xsl:if>
		<xsl:if test="SubParts/ProductPart[@PartType!='SubProduct']">
		<Subparts>
			<xsl:apply-templates select="SubParts/ProductPart[highlight #8AE234][@PartType!='SubProduct'][/highlight]"/>
		</Subparts>
		</xsl:if>
	</ProductPart>
</xsl:template>
</xsl:stylesheet>SubParts/ProductPart[@PartType!='SubProduct']"/>
		</Subparts>
		</xsl:if>
	</ProductPart>
</xsl:template>
</xsl:stylesheet>

The <xsl:if> tests were simply to avoid having self-closing (i.e. empty) tags appear since your desired XML did not show empty tages.

I hope this helps your understanding.

Tom Morrison
Hill Country Software
 
Oops. There seems to have been a little extra cruft at the end of my example code Please ignore...

Tom Morrison
Hill Country Software
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top