[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():

str-zipWith.xsl:
---------------
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>
  <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:apply-templates>

      <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)"/>
      </xsl:call-template>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>


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

test-str-zipWith.xsl:
--------------------
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 xmlns:myOr="f:myOr"
>
  <xsl:import href="str-zipWith.xsl"/>
  <!-- to be applied on numList.xml -->
  
  <xsl:output method="text"/>
  <myOr:myOr/>
  <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:call-template>
  </xsl:template>

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

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

</xsl:stylesheet>

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

test-str-zipWith.xml:
--------------------
<test-str-zipWith>
  <str>001110101000</str>
  <str>101010101001</str>
</test-str-zipWith>


The result is:
-------------
  '001110101000'
or
  '101010101001'
=
  '101110101001


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.





=====
Cheers,

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

__________________________________________________
Do you Yahoo!?
New DSL Internet Access from SBC & Yahoo!
http://sbc.yahoo.com

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


Current Thread