[xsl] Re: xsl-list Digest 10 Nov 2006 06:10:00 -0000 Issue 954

Subject: [xsl] Re: xsl-list Digest 10 Nov 2006 06:10:00 -0000 Issue 954
From: "Eric Pheatt" <eric.pheatt@xxxxxxxxx>
Date: Mon, 13 Nov 2006 13:50:40 -0800
Date: Thu, 09 Nov 2006 18:16:17 -0500
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Subject: Re: [xsl] Re: xsl-list Digest 9 Nov 2006 06:10:00 -0000 Issue
  953
Message-ID:<20061109181818.GA9737@xxxxxxxxxxxxxxxxxxxxx>

Dear Eric,

Sorry, I write in some haste.

But you will find a couple of suggestive examples of recursion in the FAQ at

http://www.dpawson.co.uk/xsl/sect2/recursion.html

Also there are plenty of others on the net, if you care to dig, or in
such classics of XSLT 1.0 lore as Jeni Tennison's _XSLT On the Edge_
and Sal Mangano's _XSLT Cookbook_.

However, I should warn you going in: you've got quite a task on your
hands if you've never done it, as XSLT 1.0 really wasn't designed for
this sort of thing. In your case, not only do you need to recurse to
generate the correct number of rows, but you will need a
string-chopping routine (itself recursive) to nibble away at the
value of @fieldnames to generate your fields. Not pretty.

[snipped]


Actually Wendell, searching the archives with your name helped immensely!

While not an elegant 5 line stylesheet, I did figure out how to do the
rows with the equivalent of a while loop, and the string chopping with
the equivalent of a list loop.

Thanks for the pointers!

For the sake of the archive here is the stylesheet fragment for XSLT
1.0 that I mashed together to simplify the WDDX recordset based on the
contextual info.

<xsl:template match="var/recordset">
   <xsl:variable name="recordsetName" select="../@name"/>
   <xsl:variable name="rowCount" select="@rowCount"/>
   <xsl:variable name="fieldNames" select="@fieldNames"/>
   <xsl:call-template name="recordsetRow">
       <xsl:with-param name="recordsetName" select="$recordsetName"/>
       <xsl:with-param name="rowCount" select="$rowCount"/>
       <xsl:with-param name="fieldNames" select="$fieldNames"/>
       <xsl:with-param name="currentRow" select="1"/>
   </xsl:call-template>
</xsl:template>

<xsl:template name="recordsetRow">
   <xsl:param name="recordsetName"/>
   <xsl:param name="rowCount"/>
   <xsl:param name="fieldNames"/>
   <xsl:param name="currentRow"/>
   <xsl:if test="$currentRow &lt;= $rowCount">
       <!-- Process current row. -->
       <xsl:element name="{$recordsetName}">
           <xsl:call-template name="recordsetColumn">
               <xsl:with-param name="fieldName" select="$fieldNames"/>
               <xsl:with-param name="currentRow" select="$currentRow"/>
               <xsl:with-param name="currentCol" select="1"/>
           </xsl:call-template>
       </xsl:element>
       <!-- Recurse to process next row. -->
       <xsl:call-template name="recordsetRow">
           <xsl:with-param name="recordsetName"
select="$recordsetName"/>
           <xsl:with-param name="rowCount" select="$rowCount"/>
           <xsl:with-param name="fieldNames" select="$fieldNames"/>
           <xsl:with-param name="currentRow" select="$currentRow + 1"/>
       </xsl:call-template>
   </xsl:if>
</xsl:template>

<xsl:template name="recordsetColumn">
   <xsl:param name="fieldName"/>
   <xsl:param name="currentRow"/>
   <xsl:param name="currentCol"/>
   <xsl:choose>
       <xsl:when test="contains($fieldName,',')">
           <!-- Select the first value to process -->
           <xsl:call-template name="recordsetField">
               <xsl:with-param name="fieldName"
select="substring-before($fieldName,',')"/>
               <xsl:with-param name="currentRow" select="$currentRow"/>
               <xsl:with-param name="currentCol" select="$currentCol"/>
           </xsl:call-template>
           <!-- Recurse with remainder of string -->
           <xsl:call-template name="recordsetColumn">
               <xsl:with-param name="fieldName"
select="substring-after($fieldName,',')"/>
               <xsl:with-param name="currentRow" select="$currentRow"/>
               <xsl:with-param name="currentCol" select="$currentCol + 1"/>
           </xsl:call-template>
       </xsl:when>
       <xsl:otherwise>
           <!-- This is the last value so we don't recurse -->
           <xsl:call-template name="recordsetField">
               <xsl:with-param name="fieldName" select="$fieldName"/>
               <xsl:with-param name="currentRow" select="$currentRow"/>
               <xsl:with-param name="currentCol" select="$currentCol"/>
           </xsl:call-template>
       </xsl:otherwise>
   </xsl:choose>
</xsl:template>

 <!-- Process of individual value here -->
<xsl:template name="recordsetField">
   <xsl:param name="fieldName"/>
   <xsl:param name="currentRow"/>
   <xsl:param name="currentCol"/>
   <xsl:variable name="fieldValue"
select="child::field[@name=$fieldName]/*[position()=$currentRow]"/>
   <xsl:element name="{$fieldName}">
       <xsl:value-of select="$fieldValue"/>
   </xsl:element>
</xsl:template>

<xsl:template match="/wddxPacket">
   <partyList>
	<xsl:apply-templates/>
   </partyList>
</xsl:template>

When applied to the following wddx packet:

<?xml version="1.0" encoding="UTF-8"?>
<wddxPacket version='1.0'><header></header><data><struct>
<var name='party'>
<recordset rowCount='3'
fieldNames='PARTY_ID,PARTY_ROLE_ID,FIRST_NAME,LAST_NAME,SUFFIX,BIRTH_DT'>
<field name='PARTY_ID'>
	<number>2127652</number>
	<number>2127653</number>
	<number>2127654</number></field>
<field name='PARTY_ROLE_ID'>
	<number>51</number>
	<number>24</number>
	<number>25</number></field>
<field name='FIRST_NAME'>
	<string>Bob</string>
	<string>Donte</string>
	<string>Mike</string></field>
<field name='LAST_NAME'>
	<string>Jones</string>
	<string>Smith</string>
	<string>Thomsone</string></field>
<field name='SUFFIX'>
	<string></string>
	<string></string>
	<string>Jr.</string></field>
<field name='BIRTH_DT'>
	<string></string>
	<dateTime>1990-6-4T0:0:0-8:0</dateTime>
	<string></string></field>
</recordset>
</var>
<var name='alias'>
<recordset rowCount='1' fieldNames='ALIAS_ID,PARTY_ID,FIRST_NAME,LAST_NAME'>
<field name='ALIAS_ID'>
	<number>1</number></field>
<field name='PARTY_ID'>
	<number>2127652</number></field>
<field name='FIRST_NAME'>
	<string>Bobby</string></field>
<field name='LAST_NAME'>
	<string>Joneson</string></field>
</recordset>
</var>
</struct></data>
</wddxPacket>

I get the following xml output.

<?xml version="1.0" encoding="UTF-8"?>
<partyList>
  <party>
     <PARTY_ID>2127652</PARTY_ID>
     <PARTY_ROLE_ID>51</PARTY_ROLE_ID>
     <FIRST_NAME>Bob</FIRST_NAME>
     <LAST_NAME>Jones</LAST_NAME>
     <SUFFIX/>
     <BIRTH_DT/>
  </party>
  <party>
     <PARTY_ID>2127653</PARTY_ID>
     <PARTY_ROLE_ID>24</PARTY_ROLE_ID>
     <FIRST_NAME>Donte</FIRST_NAME>
     <LAST_NAME>Smith</LAST_NAME>
     <SUFFIX/>
     <BIRTH_DT>1990-6-4T0:0:0-8:0</BIRTH_DT>
  </party>
  <party>
     <PARTY_ID>2127654</PARTY_ID>
     <PARTY_ROLE_ID>25</PARTY_ROLE_ID>
     <FIRST_NAME>Mike</FIRST_NAME>
     <LAST_NAME>Thomsone</LAST_NAME>
     <SUFFIX>Jr.</SUFFIX>
     <BIRTH_DT/>
  </party>

  <alias>
     <ALIAS_ID>1</ALIAS_ID>
     <PARTY_ID>2127652</PARTY_ID>
     <FIRST_NAME>Bobby</FIRST_NAME>
     <LAST_NAME>Joneson</LAST_NAME>
  </alias>
</partyList>

Current Thread