This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
A Functional Solution for "binary or" -- the str-zipWith template
- From: Dimitre Novatchev <dnovatchev at yahoo dot com>
- To: xsl-list at lists dot mulberrytech dot com
- Date: Thu, 26 Sep 2002 00:37:07 -0700 (PDT)
- Subject: [xsl] A Functional Solution for "binary or" -- the str-zipWith template
- Reply-to: xsl-list at lists dot mulberrytech dot com
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="'
'"/>
<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