Sunday, 07 October 2007

Hi

A guy on the newsgroups recently needed to create exactly 5 elements in the output of his map, no matter how many records appeared in the input.

Well, I am always looking for new things to try out, and frankly, my XSLT coding skills could be better, so I thought I'd give it a shot.

I created a project with the following input schema:

The schema is for an XML document, and has a header (1..1), a LoopingRecord (1..1) and a footer (1..1). The LoopingRecord has a Field5 element, that can appear at most 5 times.

The output schema looks like this:

This schema is for a flat file. It baiscally has the same signature as the input schema - exception being that the Field1 element has minOccurs=5. It MUST be present 5 times - this is a schema for a positional file.

The map is pretty simple:

Header and footer are mapped using regular mapping techniques. But the Detail-element is created using a custom scripting functoid.

The string concatenate functoid only has one input, the string "5". This is because I want to create exactly 5 elements in the ouput.

The custom scripting functoid is an "Inline XSLT Call TEmplate" scripting functoid with the following code:

<xsl:template name="CreateXElements">
   <xsl:param name="totalCount" />
      <Detail>
         <xsl:for-each select="/*[local-name()='InputRoot']/*[local-name()='LoopingRecord']/*[local-name()='Field5']">
            <DetailLoop>
               <Field1><xsl:value-of select="text()" /></Field1>
            </DetailLoop>
         </xsl:for-each>
         <xsl:variable name="countRecords" select="count(/*[local-name()='InputRoot']/*[local-name()='LoopingRecord']/*[local-name()='Field5'])" />
         <xsl:if test="$countRecords&lt;$totalCount + 1">
            <xsl:call-template name="BuildTheRest">
               <xsl:with-param name="counter"><xsl:value-of select="$countRecords + 1" /></xsl:with-param>
               <xsl:with-param name="totalCount"><xsl:value-of select="$totalCount" /></xsl:with-param>
            </xsl:call-template>
         </xsl:if>
      </Detail>
</xsl:template>
<xsl:template name="BuildTheRest">
   <xsl:param name="counter" />
   <xsl:param name="totalCount" />
      <DetailLoop>
         <Field1></Field1>
      </DetailLoop>
      <xsl:if test="$counter&lt;$totalCount">
         <xsl:call-template name="BuildTheRest">
            <xsl:with-param name="newCounter"><xsl:value-of select="$counter + 1" /></xsl:with-param>
         </xsl:call-template>
      </xsl:if>
</xsl:template>

Basically, I start by copying existing nodes to the destination. As I have explained in this post you need to use XSLT for the whole thing. You can't copy the existing nodes using the mapper and create the new nodes using XSLT. After the existing nodes have been copied, I create the new empty nodes, by recursively calling a template that will create a single element for me.

You can find my entire project here: CreateXNumberOfElements.zip (23.33 KB)

I hope this will come in handy for someone in the future.

--
eliasen

Sunday, 07 October 2007 00:09:42 (Romance Daylight Time, UTC+02:00)  #    Comments [4]  | 
Tuesday, 09 October 2007 20:56:03 (Romance Daylight Time, UTC+02:00)
Thanks for the followup on this item. I was able to get the input schema changed to have exactly 5 entries, but this solution will work for me in the future also.
Monday, 10 March 2008 12:34:45 (Romance Standard Time, UTC+01:00)
Hi, thanks for the entry, it was helpfull to understand, how xslt templates work.
I am looking for a example, how i can get input instances from functoids in the inline xslt script. is it possible?
dunker
Monday, 10 March 2008 22:52:19 (Romance Standard Time, UTC+01:00)
Hi

Yeah, that should be possible. But only the call template will work with parameters. You can do it with the inline XSLT scripting functoid.

--
eliasen
Thursday, 17 July 2008 20:18:51 (Romance Daylight Time, UTC+02:00)
You might also want to take a look at the table looping functoid. that's exactly what it's design for.

Have a nice day,
Chris
All comments require the approval of the site owner before being displayed.
OpenID
Please login with either your OpenID above, or your details below.
Name
E-mail
Home page

Comment (Some html is allowed: a@href@title, b, blockquote@cite, em, i, strike, strong, sub, sup, u) where the @ means "attribute." For example, you can use <a href="" title=""> or <blockquote cite="Scott">.  

Enter the code shown (prevents robots):

Live Comment Preview

Theme design by Jelle Druyts