Reputation: 25
I'm new to XSLT and I have an XML file that I'm trying to convert as a '|' delimited CSV using XSLT. There is a single cell value in CSV that needs to be computed by looping through the current and parent nodes under TPFC and concatenate all the names as the single name (Note: The parent nesting can be one or more, Here I have 2 parents in my example)
For example, the name for the below XML will be AM_Mob1_Mob2
<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Package ID="1122" BusinessID="001233" Version="19.0.2" xsi:type="Doms">
<Name>ABC</Name>
<Description> Desc sample</Description>
<Category>54</Category>
<Business_ID>001233</Business_ID>
<TPFC ID="76" xsi:type="TPFC" Pattern="Th_Branch">
<Name>AM</Name>
<Parent ID="11d" xsi:type="TPFC" Pattern="Th_Branch">
<Description>Mob1</Description>
<Name>Mob1</Name>
<Parent ID="12F" xsi:type="TPFC" Pattern="Th_Branch">
<Description>Mob2</Description>
<Name>Mob2</Name>
</Parent>
</Parent>
</TPFC>
</Package>
I tried out the params method, I'm not sure if that is the right approach but anyway I did not get the output when I tried the below snippet
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" >
<xsl:output method="text" encoding="utf-8"/>
<!-- Delimiter -->
<xsl:variable name="separator" select="'|'"/>
<xsl:template match="/">
<xsl:for-each select="//TPFC ">
<!--Nesting logic ends here-->
<xsl:param name="Concatvar">
<xsl:for-each select="Parent/Name">
<xsl:if test="Parent/Name">
<xsl:value-of select="concat($Concatvar,Parent/Name/text())"/>
</xsl:if>
</xsl:for-each>
</xsl:param>
<xsl:value-of select="$Concatvar"/>
<xsl:value-of select="$separator"/>
<--Nesting logic ends here--!>
<xsl:value-of select="normalize-space(Name)"/>
<xsl:value-of select="$separator"/>
<xsl:value-of select="normalize-space(Description)"/>
<xsl:value-of select="$separator"/>
<xsl:value-of select="normalize-space(Parent/Name)"/>
</xsl:template>
</xsl:stylesheet>
Can anyone tell me what would be the right way to write XSLT for this expected result
| id | name | description | parent_name | parent_id | level | total_level | product_offering_id |
| AM_Mob1_Mob2 | AM | Desc Sample | Mob1 | Mob1_Mob2_ | 2 | 3 | 001233 |
id - Concatenation of all names to its root parent in the below example it will be AM_Mob1_Mob2
level - if there are two levels, child is level 2 and parent is level 1
total_level - depth of the tree from TPFC + 1 i.e. no.of levels in product family hierarchy
Upvotes: 0
Views: 430
Reputation: 116959
I am afraid the logic that needs to be applied here is not clear enough.
See if this can get you started:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="utf-8"/>
<xsl:template match="/Root">
<!-- header -->
<xsl:text>id|name|description|parent_name|parent_id|... </xsl:text>
<!-- data -->
<xsl:for-each select="Package">
<xsl:variable name="pkg-desc" select="Description" />
<xsl:variable name="b-id" select="Business_ID" />
<!-- TPFC data -->
<xsl:for-each select="TPFC">
<xsl:value-of select="Name, .//Parent/Name" separator="_"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="Name"/>
<xsl:text>|</xsl:text>
<xsl:value-of select="$pkg-desc"/>
<xsl:text>|</xsl:text>
<!-- parent data -->
<xsl:value-of select="Parent/Name"/>
<xsl:text>|</xsl:text>
<xsl:value-of select=".//Parent/Name" separator="_"/>
<xsl:text>|</xsl:text>
<!-- ??? -->
</xsl:for-each>
<xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Applied to the supplied input example, the result will be:
id|name|description|parent_name|parent_id|...
AM_Mob1_Mob2|AM| Desc sample|Mob1|Mob1_Mob2|
Upvotes: 2
Reputation: 163262
This kind of thing is very much easier in XSLT 2.0 or 3.0 (but older XSLT processors only support 1.0). Your stylesheet specifies version="2.0", but you haven't tagged the question xslt-2, so I'm assuming XSLT 2.0 is available to you.
In 2.0 you can achieve the required output by writing
<xsl:value-of select="Name, Parent/Name" separator="_"/>
In 1.0 you'll need something like your current logic, but note that (a) you should be using xsl:variable
rather than xsl:param
, and (b) within xsl:for-each
, the context item changes, so within <xsl:for-each select="Parent/Name">
you should select .
, not Parent/Name
.
Upvotes: 1