[xsl] A Functional Solution for "binary or" -- the str-zipWith template

Subject: [xsl] A Functional Solution for "binary or" -- the str-zipWith template
From: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Thu, 26 Sep 2002 00:37:07 -0700 (PDT)
Rubén <rubenm at telepolis dot com> wrote: 

> Hello list! I couldn't find a "binary-or" (or "mask-or") operation in
> XPath 1.1 so I tried to emulate it with a template. I wrote a 
> recursive implementation but I'm not very happy with the result. I 
> wonder if there is a simpler (and maybe more efficient) solution. 
> Any suggestions?

Hi Rubén,

For any instance of a class of problems, requiring to perform an
operation on two lists memberwise, the functional solution is the
zipWith() function, which is implemented in FXSL.

A string is a special kind of list in XSLT, because we do not have a
"char" datatype, and cannot represent a string as a list of chars.

This is why every FXSL function, which operates on lists (implemented
as node-sets) has also a string analogue.

Here's the string analog of zipWith():

<xsl:stylesheet version="1.0"
  <xsl:template name="str-zipWith">
    <xsl:param name="pFun" select="/.."/>
    <xsl:param name="pStr1" select="/.."/>
    <xsl:param name="pStr2" select="/.."/>

    <xsl:if test="string-length($pStr1) and string-length($pStr2)">
      <xsl:apply-templates select="$pFun">
        <xsl:with-param name="pArg1" select="substring($pStr1, 1, 1)"/>
        <xsl:with-param name="pArg2" select="substring($pStr2, 1, 1)"/>

      <xsl:call-template name="str-zipWith">
        <xsl:with-param name="pFun" select="$pFun"/>
        <xsl:with-param name="pStr1" select="substring($pStr1, 2)"/>
        <xsl:with-param name="pStr2" select="substring($pStr2, 2)"/>

Now let's test it to solve your problem -- we need to "or" two strings
containing only 0-s or 1-s:

<xsl:stylesheet version="1.0"
  <xsl:import href="str-zipWith.xsl"/>
  <!-- to be applied on numList.xml -->
  <xsl:output method="text"/>
  <xsl:template match="/">
    <xsl:variable name="vApos">'</xsl:variable>
    <xsl:variable name="vNL" select="'&#xA;'"/>
    <xsl:variable name="vFun" select="document('')/*/myOr:*[1]"/>

    <xsl:value-of select="concat('  ', $vApos, /*/*[1], $vApos, $vNL,
                                 'or',  $vNL,
                                 '  ', $vApos, /*/*[2], $vApos, $vNL,
                                 '=', $vNL,
                                 '  ', $vApos
    <xsl:call-template name="str-zipWith">
      <xsl:with-param name="pFun" select="$vFun"/>
      <xsl:with-param name="pStr1" select="/*/*[1]"/>
      <xsl:with-param name="pStr2" select="/*/*[2]"/>

  <xsl:template match="myOr:*">
    <xsl:param name="pArg1"/>
    <xsl:param name="pArg2"/>

    <xsl:value-of select="number(number($pArg1) or number($pArg2))"/>


Let's apply the above transformation on the following source xml:


The result is:

I can immediately implement "binary and", "xor", some kind of primitive
encryption and ***any*** character-wise operation.

The versions of zipWith for more than two lists (and their string
analogues) are left as an exercise to the reader :o)

Hope this helped.


Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL

Do you Yahoo!?
New DSL Internet Access from SBC & Yahoo!

 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

Current Thread