XSL 1.0 Multilevel grouping with empty tags

D_O_N

New Member
This is my first time posting here, so I apologize in advance for the length and for any format issue or lack of information. I've been working on this problem for a few days and I've researched my problem extensively but haven't found a solution yet, so I am hoping someone here can help me. It's an xslt related issue and I only started coding in xslt a couple of months ago so I'm not so experienced. Basically, I have an input XML which may contain duplicate records as well as empty tags and I need to reorganize them into a javascript associative array to be able to manipulate and display the values efficiently on the client side.My question is: Is there a way to do a multilevel grouping even if the used field tag is empty. If not, is there a way I can edit the xml in xsl by replacing the empty tag with a keyword and then applying the rest of my templates? To understand my problem here are the details.This is my input XML\[code\]<cds> <sections> <section name="myteam_CurrentAgeCompleteSection" link="false"> <detail name=""> <record> <field name="AGERANGEID">30-39</field> <field name="NUMOFCOUNTAGE">1</field> <field name="ORGUNITID">00001001</field> <field name="PARENTORGUNITID">00000100</field> <field name="ORGUNITNAME">Human Resources</field> </record> <record> <field name="AGERANGEID">>=70</field> <field name="NUMOFCOUNTAGE">5</field> <field name="ORGUNITID">00001001</field> <field name="PARENTORGUNITID">00000100</field> <field name="ORGUNITNAME">Human Resources</field> </record> </detail> </section> <section name="myteam_CurrentGenderCompleteSection" link="false"> <detail name=""> <record> <field name="PARENTORGUNITID">00000100</field> <field name="ORGUNITID">00001001</field> <field name="ORGUNITNAME">Human Resources</field> <field name="NUMOFGENDERCOUNT">5</field> <field name="GENDER">2</field> </record> <record> <field name="PARENTORGUNITID">00000100</field> <field name="ORGUNITID">00001001</field> <field name="ORGUNITNAME">Human Resources</field> <field name="NUMOFGENDERCOUNT">7</field> <field name="GENDER">1</field> </record> </detail> </section> <section name="myteam_CurrentRaceCompleteSection" link="false"> <detail name=""> <record> <field name="ORGUNITNAME">Human Resources</field> <field name="PARENTORGUNITID">00000100</field> <field name="ORGUNITID">00001001</field> <field name="NUMOFRACE">10.0</field> <field name="RACENAME" /> </record> <record> <field name="ORGUNITNAME">Human Resources</field> <field name="PARENTORGUNITID">00000100</field> <field name="ORGUNITID">00001001</field> <field name="NUMOFRACE">1</field> <field name="RACENAME">Asian</field> </record> <record> <field name="ORGUNITNAME">Human Resources</field> <field name="PARENTORGUNITID">00000100</field> <field name="ORGUNITID">00001001</field> <field name="NUMOFRACE">1</field> <field name="RACENAME">American Indian</field> </record> </detail> </section> <section name="myteam_ChildAgeColumnSection" link="false"> <detail name=""> <record> <field name="AGERANGEID">40-49</field> <field name="NUMOFCOUNTAGE">1</field> <field name="ORGUNITID">50000013</field> <field name="PARENTORGUNITID">00001001</field> <field name="ORGUNITNAME">IT computer center (D)</field> </record> <record> <field name="AGERANGEID">50-59</field> <field name="NUMOFCOUNTAGE">2</field> <field name="ORGUNITID">50000013</field> <field name="PARENTORGUNITID">00001001</field> <field name="ORGUNITNAME">IT computer center (D)</field> </record> <record> <field name="AGERANGEID">>=70</field> <field name="NUMOFCOUNTAGE">5</field> <field name="ORGUNITID">50000013</field> <field name="PARENTORGUNITID">00001001</field> <field name="ORGUNITNAME">IT computer center (D)</field> </record> </detail> </section> <section name="myteam_ChildGenderColumnSection" link="false"> <detail name=""> <record> <field name="PARENTORGUNITID">00001001</field> <field name="ORGUNITID">50000013</field> <field name="ORGUNITNAME">IT computer center (D)</field> <field name="NUMOFGENDERCOUNT">4</field> <field name="GENDER">2</field> </record> <record> <field name="PARENTORGUNITID">00001001</field> <field name="ORGUNITID">50000147</field> <field name="ORGUNITNAME">Personnel Administration (D)</field> <field name="NUMOFGENDERCOUNT">3</field> <field name="GENDER">1</field> </record> <record> <field name="PARENTORGUNITID">00001001</field> <field name="ORGUNITID">50000013</field> <field name="ORGUNITNAME">IT computer center (D)</field> <field name="NUMOFGENDERCOUNT">4</field> <field name="GENDER">1</field> </record> </detail> </section> <section name="myteam_ChildGenderColumnSection" link="false"> <detail name=""> <record> <field name="PARENTORGUNITID">00001001</field> <field name="ORGUNITID">50000013</field> <field name="ORGUNITNAME">IT computer center (D)</field> <field name="NUMOFGENDERCOUNT">4</field> <field name="GENDER">2</field> </record> <record> <field name="PARENTORGUNITID">00001001</field> <field name="ORGUNITID">50000147</field> <field name="ORGUNITNAME">Personnel Administration (D)</field> <field name="NUMOFGENDERCOUNT">3</field> <field name="GENDER">1</field> </record> <record> <field name="PARENTORGUNITID">00001001</field> <field name="ORGUNITID">50000013</field> <field name="ORGUNITNAME">IT computer center (D)</field> <field name="NUMOFGENDERCOUNT">4</field> <field name="GENDER">1</field> </record> </detail> </section> <section name="myteam_ChildGenderColumnSection" link="false"> <detail name=""> <record> <field name="PARENTORGUNITID">00001001</field> <field name="ORGUNITID">50000013</field> <field name="ORGUNITNAME">IT computer center (D)</field> <field name="NUMOFGENDERCOUNT">4</field> <field name="GENDER">2</field> </record> <record> <field name="PARENTORGUNITID">00001001</field> <field name="ORGUNITID">50000147</field> <field name="ORGUNITNAME">Personnel Administration (D)</field> <field name="NUMOFGENDERCOUNT">3</field> <field name="GENDER">1</field> </record> </detail> </section> </sections></cds>\[/code\]I looked online and found that the best way to deal with multilevel grouping is to use xsl:key and generate-id(). That worked great and the data came out exactly as I wanted to, so the flow of my xsl is correct. But unfortunately if the field used in the xsl:key is an empty tag, when I go into the multilevel grouping using concat(), it fails. \[code\]<!-- Start external variables --> <!-- Field names --><xsl:variable name="ageFieldName" select="'AGERANGEID'" /><xsl:variable name="genderFieldName" select="'GENDER'" /><xsl:variable name="raceFieldName" select="'RACENAME'" /><xsl:variable name="ouIdFieldName" select="'ORGUNITID'" /><xsl:variable name="ouNameFieldName" select="'ORGUNITNAME'" /><!-- Keys --> <xsl:key use="field[@name='AGERANGEID']" name="AGERANGEID" match="detail/record" /><xsl:key use="concat(field[@name='AGERANGEID'],'|', field[@name='ORGUNITID'])" name="AGERANGEID_merge" match="detail/record" /><xsl:key use="field[@name='GENDER']" name="GENDER" match="detail/record" /><xsl:key use="concat(field[@name='GENDER'],'|', field[@name='ORGUNITID'])" name="GENDER_merge" match="detail/record" /><xsl:key use="field[@name='RACENAME']" name="RACENAME" match="detail/record" /><xsl:key use="concat(field[@name='RACENAME'],'|', field[@name='ORGUNITID'])" name="RACENAME_merge" match="detail/record" /><xsl:key use="field[@name='ORGUNITID']" name="ORGUNITID" match="detail/record" /><xsl:template match="/"> var analyticsMap = {<xsl:call-template name="buildAnalyticsTable" />};</xsl:template><xsl:template name="buildAnalyticsTable"> <!-- Age --> "<xsl:value-of select="$ageFieldName"/>" : { <xsl:apply-templates mode="buildAnalyticsTableRangeLevel" select="//detail/record[generate-id()=generate-id(key($ageFieldName, field[@name=$ageFieldName]))]"> <xsl:with-param name="keyName" select="$ageFieldName"/> <xsl:with-param name="countField" select="'NUMOFCOUNTAGE'"/> <xsl:with-param name="label" select="'Age Range'" /> <xsl:with-param name="isGender" select="'false'" /> </xsl:apply-templates> }, <!-- Gender --> "<xsl:value-of select="$genderFieldName"/>" : { <xsl:apply-templates mode="buildAnalyticsTableRangeLevel" select="//detail/record[generate-id()=generate-id(key($genderFieldName, field[@name=$genderFieldName]))]"> <xsl:with-param name="keyName" select="$genderFieldName"/> <xsl:with-param name="countField" select="'NUMOFGENDERCOUNT'"/> <xsl:with-param name="label" select="'Gender'" /> <xsl:with-param name="isGender" select="'true'" /> </xsl:apply-templates> }, <!-- Race --> "<xsl:value-of select="$raceFieldName"/>" : { <xsl:apply-templates mode="buildAnalyticsTableRangeLevel" select="//detail/record[generate-id()=generate-id(key($raceFieldName, field[@name=$raceFieldName]))]"> <xsl:with-param name="keyName" select="$raceFieldName"/> <xsl:with-param name="countField" select="'NUMOFRACE'"/> <xsl:with-param name="label" select="'Race'" /> <xsl:with-param name="isGender" select="'true'" /> </xsl:apply-templates> }</xsl:template><xsl:template match="detail/record" mode="buildAnalyticsTableRangeLevel"> <xsl:param name="keyName" /> <xsl:param name="countField" /> <xsl:param name="label" /> <xsl:param name="isGender" /> <xsl:variable name="value" > <xsl:call-template name="testForUnknown"> <xsl:with-param name="name" select="field[@name=$keyName]"/> </xsl:call-template> </xsl:variable> <xsl:variable name="name"> <xsl:call-template name="testForGender"> <xsl:with-param name="isGender" select="$isGender"/> <xsl:with-param name="name" select="$value"/> </xsl:call-template> </xsl:variable> "<xsl:value-of select="$value"/>" : { "analyticsLabel" : "<xsl:value-of select="$label"/>", "analyticsName" : "<xsl:value-of select="$name"/>", <xsl:apply-templates mode="buildAnalyticsTableCountLevel" select="key($keyName, field[@name=$keyName])[generate-id()=generate-id(key(concat($keyName, '_merge'), concat(field[@name=$keyName],'|', field[@name=$ouIdFieldName])))]"> <xsl:with-param name="countField" select="$countField"/> </xsl:apply-templates> }, </xsl:template><xsl:template match="detail/record" mode="buildAnalyticsTableCountLevel"> <xsl:param name="countField" /> "<xsl:value-of select="field[@name=$ouIdFieldName]"/>" : { "analyticsOUname" : "<xsl:value-of select="field[@name=$ouNameFieldName]"/>", "analyticsValue" : "<xsl:value-of select="field[@name=$countField]"/>" },</xsl:template> <xsl:template name="testForUnknown"> <xsl:param name="name" /> <xsl:choose> <xsl:when test="string-length($name) = 0"> <xsl:value-of select="'Unknown'"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="$name" /> </xsl:otherwise> </xsl:choose></xsl:template><xsl:template name="testForGender"> <xsl:param name="isGender" /> <xsl:param name="name" /> <xsl:choose> <xsl:when test="$isGender = 'true' and $name = 1"> <xsl:value-of select="'male'" /> </xsl:when> <xsl:when test="$isGender = 'true' and $name = 2"> <xsl:value-of select="'female'" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="$name" /> </xsl:otherwise> </xsl:choose></xsl:template>\[/code\]Here is the output of my transformation\[code\] var analyticsMap = { "AGERANGEID" : { "30-39" : { "analyticsLabel" : "Age Range", "analyticsName" : "30-39", "00001001" : { "analyticsOUname" : "Human Resources", "analyticsValue" : "1" }, }, ">=70" : { "analyticsLabel" : "Age Range", "analyticsName" : ">=70", "00001001" : { "analyticsOUname" : "Human Resources", "analyticsValue" : "5" }, "50000013" : { "analyticsOUname" : "IT computer center (D)", "analyticsValue" : "5" }, }, "40-49" : { "analyticsLabel" : "Age Range", "analyticsName" : "40-49", "50000013" : { "analyticsOUname" : "IT computer center (D)", "analyticsValue" : "1" }, }, "50-59" : { "analyticsLabel" : "Age Range", "analyticsName" : "50-59", "50000013" : { "analyticsOUname" : "IT computer center (D)", "analyticsValue" : "2" }, }, }, "GENDER" : { "2" : { "analyticsLabel" : "Gender", "analyticsName" : "female", "00001001" : { "analyticsOUname" : "Human Resources", "analyticsValue" : "5" }, "50000013" : { "analyticsOUname" : "IT computer center (D)", "analyticsValue" : "4" }, }, "1" : { "analyticsLabel" : "Gender", "analyticsName" : "male", "00001001" : { "analyticsOUname" : "Human Resources", "analyticsValue" : "7" }, "50000147" : { "analyticsOUname" : "Personnel Administration (D)", "analyticsValue" : "3" }, "50000013" : { "analyticsOUname" : "IT computer center (D)", "analyticsValue" : "4" }, }, }, "RACENAME" : { "Unknown" : { "analyticsLabel" : "Race", "analyticsName" : "Unknown", }, "Asian" : { "analyticsLabel" : "Race", "analyticsName" : "Asian", "00001001" : { "analyticsOUname" : "Human Resources", "analyticsValue" : "1" }, }, "American Indian" : { "analyticsLabel" : "Race", "analyticsName" : "American Indian", "00001001" : { "analyticsOUname" : "Human Resources", "analyticsValue" : "1" }, }, }};\[/code\]As you can see, in the Race->Unknown section, it doesn't complete it by applying the template mode "buildAnalyticsTableCountLevel" so I never get the ORGUNITID information which is very important in what I am doing.I unfortunately cannot edit the xml coming in as this is a part of a much bigger framework used in various projects and I cannot change it. So I have to work with what I get.I tried using the string() method in xsl:key but that makes everything worse. Any tips or help is appreciated. Thanks in advance!
 
Back
Top