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]

Re: seperating alphanumeric string in two preferably using fxsl


"Bryan Rasmussen" <bry at itnisk dot com> wrote:

> I've got elements that will have alphanumeric strings in the format 
> of css values, for example 11px or 150%(would one classify that as 
> alphanumeric?) or 5em, 5.5in and so forth. normally what I would do 
> is have a parameter with a nodeset of values like
> <value>in</value>
> <value>em</value>
> then a variable that gets the value that is contained in my element, 
> then get the substring-before the value. Am thinking someone might 
> have either a generic template that already does something like this
> (help me not to work!), or can give me a better suggestion for how I 
> should build my template(help me to improve myself!), or maybe 
> Dimitre has an idea how this could be done using the fxsl library
> (help me develop my brain!).

Hi Bryan,

Let me first thank you for your interest in the FXSL functional
programming library and let me assure you that some new, important
modules of functions have already been implemented and will be
published in the nearest future.

Your problem can be solved in a purely functional style using the
string analog of span(). FXSL already contains many string analogues of
the list processing functions (e.g. str-takeWhile() str-dropWhile() ).
The reason why we must have string analogs for the list-processing
functions is than neither in XPath 1.0 nor in XPath 2.0 a string can be
represented and treated just as a sequence of characters.

As other people have already pointed out, splitting a string into two
parts according to a condition can almost always be done effectively
using the standard XPath function translate().

However, translate will not be so convenient to use if the string to be
split and the condition are created dynamically (not known in advance),
or if the string may be comprised of any of many different characters
(e.g. all Unicode characters).

Another case is when the condition is a function not of a single
character only.

In these cases using translate will be either inconvenient or
impossible (in the last case).

Here's a function  --  strSpan(), which is the string analog of  the
span() function. It takes a string, a predicate, which acts on a single
character, two element names for the nodes that will be returned, that
will contain the results. The first of these nodes will contain the
longest substring of characters of the string starting from the first
character, which all satisfy the predicate. The second node will
contain the rest of the string.

strSpan.xsl:
-----------
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
>
  <xsl:import href="str-takeWhile.xsl"/>
  
  <xsl:template name="strSpan">
    <xsl:param name="pStr" />
    <xsl:param name="pController" select="/.."/>
    <xsl:param name="pContollerParam" select="/.."/>
    <xsl:param name="pElementName1" select="'el1'"/>
    <xsl:param name="pElementName2" select="'el2'"/>
    
    <xsl:variable name="vPositive">
      <xsl:call-template name="str-takeWhile">
	  <xsl:with-param name="pStr" select="$pStr"/>
	  <xsl:with-param name="pController" select="$pController"/>
	  <xsl:with-param name="pContollerParam" 
                          select="$pContollerParam"/>
      </xsl:call-template>
    </xsl:variable>
    
    <xsl:element name="{$pElementName1}">
      <xsl:copy-of select="$vPositive"/>
    </xsl:element>
    
    <xsl:element name="{$pElementName2}">
      <xsl:copy-of select="substring($pStr, 
                                     string-length($vPositive) + 1
                                     )"/>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet> 

Here's a stylesheet demonstrating how to use the strSpan() function:

test-strSpan.xsl:
----------------
<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 xmlns:myController="f:myController"
 xmlns:x="f:myTest"
 >
  <xsl:import href="strSpan.xsl"/>
  
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  
  <myController:myController/>
  
  <xsl:variable name="x:st" select="document('')/*"/>
  
  <xsl:template match="/">
    <xsl:call-template name="strSpan">
      <xsl:with-param name="pStr" select="string(/*)"/>
      <xsl:with-param name="pController" 
                      select="$x:st/myController:*[1]"/>
      <xsl:with-param name="pContollerParam" 
                      select="'0123456789.'"/>
      <xsl:with-param name="pElementName1" select="'value'"/>
      <xsl:with-param name="pElementName2" select="'unit'"/>
    </xsl:call-template>
  </xsl:template>
  
  <xsl:template match="myController:*">
    <xsl:param name="pChar"/>
    <xsl:param name="pParams"/>
    
    <xsl:if test="contains($pParams, $pChar)">1</xsl:if>
  </xsl:template>
</xsl:stylesheet>

When applied on the following source xml document:

csstext.xml:
-----------
<csstext>5.5in</csstext>

it produces the following result:

<value>5.5</value>
<unit>in</unit>


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]