XSLT Grouping flat XML -
i have flat xml file coming database. need group data more hierarchical layout using xsl transformation. have researched quite bit , come meunchian grouping way go can't work.
i going from:
<report> <data> <row> <field name ="assessmentid">1</field> <field name ="company">test company</field> <field name ="manager">bob smith</field> <field name ="issueid">1-1</field> <field name ="issuetitle">security problem</field> <field name ="issuedescription">some description</field> </row> <row> <field name ="assessmentid">1</field> <field name ="company">test company</field> <field name ="manager">bob smith</field> <field name ="issueid">1-2</field> <field name ="issuetitle">other problem</field> <field name ="issuedescription">some other description</field> </row> </data> </report> to this:
<assessments> <assessment> <assessmentid>1</assessmentid> <company>test company</company> <manager>bob smith</manager> <issue> <issueid>1-1</issueid> <issuetitle>security problem</issuetitle> <issuedescription>some description</issuedescription> </issue> <issue> <issueid>1-2</issueid> <issuetitle>other problem</issuetitle> <issuedescription>some other description</issuedescription> </issue> </assessment> </assessments> this code i've come far:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:key name="keyassessmentid" match="row" use="field[@name='assessmentid']"/> <xsl:key name="keyissueid" match="row" use="field[@name='issueid']"/> <xsl:template match="/"> <assessments> <!-- process each assessment --> <xsl:for-each select="//row[generate-id(.) = generate-id(key('keyassessmentid', field[@name='assessmentid'])[1])]"> <!-- select issues belonging assessment --> <xsl:variable name ="lngassessmentid"><xsl:value-of select="field[@name='assessmentid']" /></xsl:variable> <xsl:variable name="lstissue" select="//row[field[@name='issueid']=$lngassessmentid]" /> <!-- show details issues in assessments --> <xsl:call-template name="showissuesinassessment"> <xsl:with-param name="lstissue" select="$lstissue" /> </xsl:call-template> </xsl:for-each> </assessments> </xsl:template> <xsl:template name="showissuesinassessment"> <xsl:param name="lstissue" /> <!-- show name of assessment being processed --> <assessmentid> <xsl:value-of select="$lstissue[1]/field[@name='assessmentid']" /> </assessmentid> <!-- show issueid each issue in assessment --> <xsl:for-each select="$lstissue[generate-id(.) = generate-id(key('keyissueid', field[@name='issueid'])[1])]"> <xsl:variable name="lngissueid" select="field[@name='issueid']" /> <!-- show details of each issue --> <issue> <issueid> <xsl:value-of select="$lstissue[field[@name='issueid']=$lngissueid]/field[@name='issueid']" /> </issueid> <issuetitle> <xsl:value-of select="$lstissue[field[@name='issueid']=$lngissueid]/field[@name='issuetitle']" /> </issuetitle> </issue> </xsl:for-each> </xsl:template> </xsl:stylesheet> i working off of example on codeproject: here
thanks assistance!
you've started off correctly using muenchian grouping first occurrence of each assessmentid
<xsl:for-each select="//row[generate-id(.) = generate-id(key('keyassessmentid', field[@name='assessmentid'])[1])]"> but "issues" assessment, should using key (where $assessmentid variable containing assessmentid)
<xsl:apply-templates select="key('keyassessmentid', $assessmentid)"/> i can't see need use xsl:call-template here, or pass in elements in group parameter. use template matching, xslt at. in template matches row, can output issue details
<xsl:template match="row"> <issue> <xsl:apply-templates select="field[@name='issueid']"/> <xsl:apply-templates select="field[@name='issuetitle']"/> <xsl:apply-templates select="field[@name='issuedescription']"/> </issue> </xsl:template> and save code repetition can have single template matching these variable fields
<xsl:template match="row/*"> <xsl:element name="{@name}"> <xsl:value-of select="."/> </xsl:element> </xsl:template> (this makes use of "attribute value templates" create element name based on value of @name attribute field).
try xslt
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/xsl/transform" version="1.0"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:key name="keyassessmentid" match="row" use="field[@name='assessmentid']"/> <xsl:template match="/*"> <assessments> <xsl:for-each select=".//row[generate-id(.) = generate-id(key('keyassessmentid', field[@name='assessmentid'])[1])]"> <xsl:variable name="assessmentid" select="field[@name='assessmentid']"/> <assessment> <assessmentid> <xsl:value-of select="$assessmentid"/> </assessmentid> <xsl:apply-templates select="key('keyassessmentid', $assessmentid)"/> </assessment> </xsl:for-each> </assessments> </xsl:template> <xsl:template match="row"> <issue> <xsl:apply-templates select="field[@name='issueid']"/> <xsl:apply-templates select="field[@name='issuetitle']"/> <xsl:apply-templates select="field[@name='issuedescription']"/> </issue> </xsl:template> <xsl:template match="row/*"> <xsl:element name="{@name}"> <xsl:value-of select="."/> </xsl:element> </xsl:template> </xsl:stylesheet> then, have read of http://www.jenitennison.com/xslt/grouping/muenchian.html better understanding of muenchian grouping.
Comments
Post a Comment