This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

The filter and str-filter functions (Was: Re: How to filter characters from a string?)


Greg Faron <gfaron at integretechpub dot com> wrote:

>    I'm practicing XSLT and decided to write my own Base 64 encoder 
> and decoder templates.  The rules for Base 64 Encoding say that only 
> the following characters (in an encoded file) should be examined upon

> decoding:
> <xsl:variable name="base64Map" 
>select="'ABCDEFGHIJKLMNOPQRSTUVWXYZabcedfghijklmnopqrstuvwxyz01234567890+/='"/>
> 
>    This means that I would like to filter out every character that is

> not one of the 65 above characters.  I realize that I could do this 
> partially with translate(), but then I would need to specify every 
> possible illegal character, of which there are thousands (if you have

> Unicode characters in there).  A smaller version of such a command 
> would be translate($encodedString,
>            $base64Map,
>            concat($base64Map,
>                   '=&#xA;&#xD; 
> `~!@#$%^&amp;*()-_)&quot;&apos;[]{}|\&lt;&gt;,.?;:'))
> 
>    Are there any templates or commands to delete any character from 
> the first argument that DOESN'T appear in the second argument?  I'm 
> using Microsoft XSLT engine MSXSL4.

Hi Greg,

Here's a function from the next release of FXSL, which filters
characters from a string using a given predicate (condition) function.

This function is str-filter() and is the string analog of the filter()
function, which filters nodes from a node-set.

str-filter.xsl:
--------------
<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
>

  <xsl:template name="str-filter">
    <xsl:param name="pStr"/>
    <xsl:param name="pController" select="/.."/>
    <xsl:param name="pElName" select="'str'"/>
    
    <xsl:element name="{$pElName}">
      <xsl:call-template name="_str-filter">
        <xsl:with-param name="pStr" select="$pStr"/>
        <xsl:with-param name="pController" select="$pController"/>
      </xsl:call-template>
    </xsl:element>

  </xsl:template>    

  <xsl:template name="_str-filter">
    <xsl:param name="pStr" />
    <xsl:param name="pController" select="/.."/>

    <xsl:if test="not($pController)">
      <xsl:message terminate="yes">
         [str-filter]Error: pController not specified.
      </xsl:message>
    </xsl:if>
    
    <xsl:if test="$pStr">
      <xsl:variable name="vthisChar" select="substring($pStr, 1, 1)"/>
		  
		  <xsl:variable name="vHolds">
		    <xsl:apply-templates select="$pController">
		      <xsl:with-param name="arg1" select="$vthisChar"/>
		    </xsl:apply-templates>
		  </xsl:variable>
	    
	    <xsl:if test="string($vHolds)">
	      <xsl:copy-of select="$vthisChar"/>
	    </xsl:if>
	    
	    <xsl:call-template name="_str-filter">
	      <xsl:with-param name="pStr" select="substring($pStr, 2)"/>
	      <xsl:with-param name="pController" select="$pController"/>
	    </xsl:call-template>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

And here's a small test:

teststr-Filter.xsl:
------------------
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:myIsAlpha="f:myIsAlpha"
>
 
  <xsl:import href="str-filter.xsl"/>
  
  <!-- To be applied on any input xml file -->
 
  <xsl:output indent="yes" omit-xml-declaration="yes"/>
  
  <myIsAlpha:myIsAlpha/>
  
  <xsl:template match="/">
    <xsl:variable name="vIsAlpha"
select="document('')/*/myIsAlpha:*[1]"/>
    
    Filtering by IsAlpha: 
    
    filter('A1b3C67DE+', IsAlpha) =
    <xsl:call-template name="str-filter">
	    <xsl:with-param name="pStr" select="'A1b3C67DE+'"/>
	    <xsl:with-param name="pController" select="$vIsAlpha"/>
    </xsl:call-template>
  </xsl:template>
  
  <xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
  <xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>
  <xsl:variable name="vAlpha" select="concat($vUpper, $vLower)"/>
  
  <xsl:template name="myIsAlpha" match="myIsAlpha:*">
    <xsl:param name="arg1"/>
    
    <xsl:if test="contains($vAlpha, $arg1)">1</xsl:if>
  </xsl:template>
</xsl:stylesheet>

The result of applying this transformation is:

    Filtering by IsAlpha: 
    
    filter('A1b3C67DE+', IsAlpha) =
    <str>AbCDE</str>


Hope this helped.

Cheers,
Dimitre Novatchev.




__________________________________________________
Do You Yahoo!?
Yahoo! Movies - coverage of the 74th Academy Awards®
http://movies.yahoo.com/

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]