[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

Re: [xsl] Conditional String Substitution


Subject: Re: [xsl] Conditional String Substitution
From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx>
Date: Sat, 26 Apr 2008 08:10:13 -0700

On Fri, Apr 25, 2008 at 9:15 PM, Nathan Potter <ndp@xxxxxxxxxxxxxxxxxxxx> wrote:
>
>  On Apr 25, 2008, at 11:46 AM, Dimitre Novatchev wrote:
>
>
> >
> > > I need to look at the value of the attribute "href" and determine if it
> ends
> > > in the suffix ".xml"
> > >
> > > If so then I need to replace the ".xml" suffix with a ".html" suffix.
> > >
> > > I got it to work using a pretty convoluted set of XPath expressions in
> > > conjunction with xsl:if but I think that I am missing something...
> > >
> >
> > This can be accomplished with a single XPath 1.0 expression:
> >
> > concat(substring(@x,
> >                 1,
> >                 string-length(@x)
> >                  -4
> >                 *
> >                  (substring(@x, string-length(@x)-3) = '.xml')
> >                ),
> >
> >                substring('.html',
> >                           1
> >                         div
> >                          (substring(@x, string-length(@x)-3) = '.xml')
> >                         )
> >       )
> >
> >
>
>  I picked the first parameter of the concat apart and I understand how it
> works.
>
>
>  When I try to isolate the second parameter:
>
>
>     substring('.html',1 div(substring(@href, string-length(@href)-3) =
> '.xml'))
>
>
>  My transformer won't parse it. Oddly, it works fine when imbedded in your
> example.

Probably you need to have "div (...)"  instead of "div(...)"   .

div  is an  operator -- not a function.

>
>  Can you explain how it works?


The following expression:
   substring(@href, string-length(@href)-3)

evaluates to the string, formed by the last four characters in @href.
Let's call it $vEnding4

The following expression:
   (substring(@x, string-length(@x)-3) = '.xml')

will be more understandable to write as:

  ($vEnding4 = '.xml')

and it evaluates to either of the boolean true() or false(). Let's
call this expression $vEndsWithXML

Then

 1 div (substring(@x, string-length(@x)-3) = '.xml')

is equivalent to

 1 div   ($vEnding4 = '.xml')

and it is equivalent to

 1 div $vEndsWithXML

Now, $vEndsWithXML is of type boolean, but is used in the expression
as a number. XPath 1.0 performs a dynamic cast of
   true()   --> 1
   false() --> 0

Therefore, if the string value of @href ends with ".xml", the above
expression is equivalent to

  1 div 1

which evaluates to 1.

On the other hand,  if the string value of @href does not end in
".xml" the above expression is equivalent to

  1 div 0

which evaluates to Infinity.


Finally, we can explain what will be the result of the evaluation of
the second argument of concat() in the complete expression:

   substring('.html',
                       1
                     div
                        (substring(@x, string-length(@x)-3) = '.xml')
                     )

is equivalent to:

   substring('.html', 1)    --> when @x ends in '.xml'

or to

   substring('.html', Infinity)    --> when @x does not end in '.xml'

Thus the above two expressions will be evaluated (correspondingly) to:

 '.html'     --> when @x ends in '.xml'

or

""  --> when @x does not end in '.xml'


Then, the complete expression:

concat(substring(@x,
                1,
                string-length(@x)
                 -4
                *
                 (substring(@x, string-length(@x)-3) = '.xml')
               ),

               substring('.html',
                          1
                        div
                         (substring(@x, string-length(@x)-3) = '.xml')
                        )
      )


means:

concat the following two arguments:

arg1:

   @x  --> if @x does not end in ".xml"

or
   (substring(@x,
                  1,
                  string-length(@x)
                   -4
   )

        --> if @x ends in ".xml".  That is, all the string @x without
the ending ".xml".


arg2:

     "" (the empty string)  --> if @x does not end in ".xml"
or

   ".html"  --> if @x does ends in ".xml"


And the result of the evaluation is either:

     the string @x (if it does not enf in ".xml")

or

   the string @x with its ending ".xml" taken out and the ending
".html" appended.



-- 
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
Never fight an inanimate object
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play


>
>
>
>  Thanks,
>
>
>
>
>  N
>
>
>
>
> >
> >
> >
> >
> > --
> > Cheers,
> > Dimitre Novatchev
> > ---------------------------------------
> > Truly great madness cannot be achieved without significant intelligence.
> > ---------------------------------------
> > To invent, you need a good imagination and a pile of junk
> > -------------------------------------
> > Never fight an inanimate object
> > -------------------------------------
> > You've achieved success in your field when you don't know whether what
> > you're doing is work or play
> >
> >
> >
> > On Fri, Apr 25, 2008 at 10:22 AM, Nathan Potter
> > <ndp@xxxxxxxxxxxxxxxxxxxx> wrote:
> >
> > >
> > >
> > > Greetings,
> > >
> > > I need to do some string manipulation of an attribute value using XSLT.
> > >
> > > I need to look at the value of the attribute "href" and determine if it
> ends
> > > in the suffix ".xml"
> > >
> > > If so then I need to replace the ".xml" suffix with a ".html" suffix.
> > >
> > > I got it to work using a pretty convoluted set of XPath expressions in
> > > conjunction with xsl:if but I think that I am missing something...
> > >
> > > Is there a more straight forward way of accomplishing this?
> > >
> > >
> > > Example(s):
> > >
> > >   <xsl:template match="thredds:catalogRef">
> > >
> > >       <xsl:variable name="href" select="./@xlink:href" />
> > >       <xsl:variable name="linkSuffix"
> > > select="substring($href,string-length($href) - 3)" />
> > >       <xsl:variable name="linkBody"
> > > select="substring($href,1,string-length($href) - 4)" />
> > >
> > >       <xsl:if test="$linkSuffix='.xml'">
> > >           <xsl:value-of select="$indent"/><a
> > > href="{concat($linkBody,'.html')}" ><xsl:value-of
> select="./@xlink:title"/>
> > > /</a>
> > >       </xsl:if>
> > >
> > >       <xsl:if test="not($linkSuffix='.xml')">
> > >           <xsl:value-of select="$indent"/><a href="{$href}"
> ><xsl:value-of
> > > select="./@xlink:title"/> /</a>
> > >       </xsl:if>
> > >
> > >   </xsl:template>
> > >
> > >
> > >
> > > I used a bunch of variables in the example simply to make it more
> readable,
> > > the example could be condensed to:
> > >
> > >   <xsl:template match="thredds:catalogRef">
> > >
> > >       <xsl:if test="substring(./@xlink:href,string-length(./@xlink:href)
> -
> > > 3)='.xml'">
> > >           <a
> > > href="{concat(substring(./@xlink:href,1,string-length(./@xlink:href) -
> > > 4),'.html')}" ><xsl:value-of select="./@xlink:title"/> /</a>
> > >       </xsl:if>
> > >
> > >       <xsl:if
> > > test="not(substring(./@xlink:href,string-length(./@xlink:href) - 3))">
> > >           <a href="{./@xlink:href}" ><xsl:value-of
> > > select="./@xlink:title"/> /</a>
> > >       </xsl:if>
> > >       <br/>
> > >
> > >   </xsl:template>
> > >
> > > Thanks!
> > >
> > > Nathan
> > >
> > >
> > >
> > >
> > >
> > >
> > > ============================================================
> > > Nathan Potter                 Oregon State University, COAS
> > > ndp at coas.oregonstate.edu   104 Ocean. Admin. Bldg.
> > > 541 737 2293 voice            Corvallis, OR   97331-5503
> > > 541 737 2064 fax
> >
> >
>
>  ============================================================
>  Nathan Potter                 Oregon State University, COAS
>  ndp at coas.oregonstate.edu   104 Ocean. Admin. Bldg.
>  541 737 2293 voice            Corvallis, OR   97331-5503
>  541 737 2064 fax


Current Thread
Keywords