[Home] [By Thread] [By Date] [Recent Entries]
reynaldo.rizzo@xxxxxxxxxxxxxxxx wrote:
The desired output is a delimited file shown as follows: Here is an XSLT 2.0 stylesheet that produces the above output, with the exception of the first line where I have left out the 'root,' at the beginning.
<xsl:output method="text"/> <xsl:param name="lf" select="' '" as="xs:string"/> <xsl:param name="sep" select="','" as="xs:string"/> <xsl:param name="default" select="'null'" as="xs:string"/> <xsl:template match="/"> <xsl:variable name="max-items" select="max(root/item/count((* except (code, name))))"/> <xsl:variable name="item-list" select="root/item[count(* except (code, name)) eq $max-items][1]/(* except (code, name))"/> <xsl:value-of select="('itemCode', 'itemName', $item-list/(concat(substring-before(name(), 'List'), 'Code'), concat(substring-before(name(), 'List'), 'Description')))" separator="{$sep}"/> <xsl:value-of select="$lf"/> <xsl:for-each select="root/item">
<xsl:call-template name="mf:make-lines">
<xsl:with-param name="item" select="."/>
<xsl:with-param name="item-list" select="$item-list"/>
</xsl:call-template>
</xsl:for-each></xsl:template> <xsl:template name="mf:make-lines"> <xsl:param name="item" as="element()"/> <xsl:param name="item-list" as="element()*"/> <xsl:param name="line" as="item()*" select="()"/> <xsl:variable name="current-list" as="element()?" select="$item/*[node-name(.) eq node-name($item-list[1])]"/> <xsl:choose> <xsl:when test="count($item-list) eq 1"> <xsl:choose> <xsl:when test="$current-list"> <xsl:for-each select="$current-list/*"> <xsl:value-of select="($item/code, $item/name, $line, code, description)" separator="{$sep}"/> <xsl:value-of select="$lf"/> </xsl:for-each> </xsl:when> <xsl:otherwise> <xsl:value-of select="($item/code, $item/name, $line, $default, $default)" separator="{$sep}"/> <xsl:value-of select="$lf"/> </xsl:otherwise> </xsl:choose> </xsl:when> <xsl:otherwise> <xsl:choose> <xsl:when test="$current-list"> <xsl:for-each select="$current-list/*"> <xsl:call-template name="mf:make-lines"> <xsl:with-param name="item" select="$item"/> <xsl:with-param name="item-list" select="$item-list[position() gt 1]"/> <xsl:with-param name="line" select="($line, code, description)"/> </xsl:call-template> </xsl:for-each> </xsl:when> <xsl:otherwise> <xsl:call-template name="mf:make-lines"> <xsl:with-param name="item" select="$item"/> <xsl:with-param name="item-list" select="$item-list[position() gt 1]"/> <xsl:with-param name="line" select="($line, $default, $default)"/> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> To decide which *List elements to output the stylesheet looks for the maximum number of child elements of an 'item' element, then for each 'item' element the named template mf:make-lines is called, passing in the item element and the item list. That template recursively builds each line to be output as a sequence, shortening the item list each time. -- Martin Honnen http://msmvps.com/blogs/martin_honnen/
|

Cart



