[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Multiple replace() in XSLT 2

Subject: Re: Multiple replace() in XSLT 2
From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sun, 19 May 2019 04:57:22 -0000
Re:  Multiple replace() in XSLT 2
Sorry,

Found a minor issue with the posted solution (likely a pasting mistake).
Here is the corrected solution:

<xsl:stylesheet version="2.0" xmlns:xsl="
http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

    <my:params xml:space="preserve">
        <pattern>
          <old>corelation</old>
          <new>dependency</new>
        </pattern>
        <pattern>
          <old>relation</old>
          <new>tie</new>
        </pattern>
        <pattern>
            <old>&#xA;</old>
            <new><br/></new>
        </pattern>
        <pattern>
            <old>quick</old>
            <new>slow</new>
        </pattern>
        <pattern>
            <old>fox</old>
            <new>elephant</new>
        </pattern>
        <pattern>
            <old>brown</old>
            <new>white</new>
        </pattern>
    </my:params>

    <xsl:variable name="vPatterns"
         select="document('')/*/my:params/*"/>

   <xsl:template match="/">
    <xsl:sequence select="my:MultuReplace(/*)"/>
   </xsl:template>

   <xsl:function name="my:MultuReplace">
     <xsl:param name="pText" as="xs:string*"/>

     <xsl:variable name="vStartingIndexes" select=
     "for $ind in 1 to string-length($pText),
          $hasMatchingPattern in
exists($vPatterns[starts-with(substring($pText, $ind), old)])
       return
          $ind[$hasMatchingPattern]
     "/>


     <xsl:variable name="actualIndexes" select=
     "for $pos in 1 to count($vStartingIndexes),
          $ind in $vStartingIndexes[$pos]
       return
         if($pos = 1) then $ind
         else
           (for $prevInd in $vStartingIndexes[$pos -1],
                $prevReplacementLength in
string-length($vPatterns[starts-with(substring($pText, $prevInd),
old)][1]/old)
             return
               if($prevReplacementLength le $ind - $prevInd)
                 then $ind
                 else ()
           )
     "/>

     <xsl:variable name="vResultSequence" as="xs:string*">
   <xsl:sequence select=
   "for $pos in  1 to count($actualIndexes),
        $indRepl in $actualIndexes[$pos],
        $startUnprocessedText in
          (if($pos = 1)
             then 1
             else
               (for $indLastReplacedText in $actualIndexes[$pos -1],
                    $last-replacedText in
$vPatterns[starts-with(substring($pText, $indLastReplacedText),
old)][1]/old,
                    $lastReplacementLength in
string-length($last-replacedText)
                   return
                     $actualIndexes[$pos -1] +
string-length($last-replacedText)
                 )
          )
     return
       ( concat(
        substring($pText, $startUnprocessedText, $indRepl -
$startUnprocessedText),
        $vPatterns[starts-with(substring($pText, $indRepl),
old)][1]/new/string()
                )
        )
   "/>

   <xsl:sequence select=
    "for $lastReplIndex in $actualIndexes[last()],
         $last-replacedText in $vPatterns[starts-with(substring($pText,
$lastReplIndex), old)][1]/old,
         $lastReplacementLength in string-length($last-replacedText)
      return
         substring($pText, $lastReplIndex + $lastReplacementLength)
    "/>
      </xsl:variable>

      <xsl:sequence select="string-join($vResultSequence, '')"/>
  </xsl:function>
</xsl:stylesheet>

Cheers,
Dimitre

On Sat, May 18, 2019 at 1:21 PM Dimitre Novatchev <dnovatchev@xxxxxxxxx>
wrote:

> This was an XSLT 1.0 recursive solution:
>
>      https://stackoverflow.com/a/5283744/36305
>
> Based on this algorithm one can produce a non-recursive XSLT 2.0 solution
> (and even a single XPath 2 expression).
>
> Here is a first, non-polished but working non-recursive MultiReplace
> implementation in XSLT 2.0 -- just 58 lines and  well-formatted. This
> implementation also solves the problem of overlapping replacement patterns:
>
> <xsl:stylesheet version="2.0" xmlns:xsl="
> http://www.w3.org/1999/XSL/Transform"
>  xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="my:my">
>  <xsl:output omit-xml-declaration="yes" indent="yes"/>
>  <xsl:strip-space elements="*"/>
>
>     <my:params xml:space="preserve">
>         <pattern>
>           <old>corelation</old>
>           <new>dependency</new>
>         </pattern>
>         <pattern>
>           <old>relation</old>
>           <new>tie</new>
>         </pattern>
>         <pattern>
>             <old>&#xA;</old>
>             <new><br/></new>
>         </pattern>
>         <pattern>
>             <old>quick</old>
>             <new>slow</new>
>         </pattern>
>         <pattern>
>             <old>fox</old>
>             <new>elephant</new>
>         </pattern>
>         <pattern>
>             <old>brown</old>
>             <new>white</new>
>         </pattern>
>     </my:params>
>
>     <xsl:variable name="vPatterns"
>          select="document('')/*/my:params/*"/>
>
>    <xsl:template match="/">
>     <xsl:sequence select="my:MultuReplace(/*)"/>
>    </xsl:template>
>
>    <xsl:function name="my:MultuReplace">
>      <xsl:param name="pText" as="xs:string*"/>
>
>      <xsl:variable name="vStartingIndexes" select=
>      "for $ind in 1 to string-length($pText),
>           $hasMatchingPattern in
> exists($vPatterns[starts-with(substring($pText, $ind), old)])
>        return
>           $ind[$hasMatchingPattern]
>      "/>
>
>      <xsl:variable name="actualIndexes" select=
>      "for $ind in $vStartingIndexes
>        return $ind
>        [position() = 1
>        or
>          (for $pos in position()[position() > 1],
>              $prevInd in $vStartingIndexes[$pos -1],
>              $prevReplacementLength in
> string-length($vPatterns[starts-with(substring($pText, $prevInd),
> old)][1]/old)
>           return
>              $prevReplacementLength le $ind - $prevInd
>          )
>        ]
>      "/>
>
>      <xsl:variable name="vResultSequence" as="xs:string*">
>     <xsl:sequence select=
>     "for $pos in  1 to count($actualIndexes),
>          $indRepl in $actualIndexes[$pos],
>          $startUnprocessedText in
>            (if($pos = 1)
>               then 1
>               else
>                 (for $indLastReplacedText in $actualIndexes[$pos -1],
>                      $last-replacedText in
> $vPatterns[starts-with(substring($pText, $indLastReplacedText),
> old)][1]/old,
>                      $lastReplacementLength in
> string-length($last-replacedText)
>                     return
>                       $actualIndexes[$pos -1] +
> string-length($last-replacedText)
>                   )
>            )
>       return
>         ( concat(
>          substring($pText, $startUnprocessedText, $indRepl -
> $startUnprocessedText),
>          $vPatterns[starts-with(substring($pText, $indRepl),
> old)][1]/new/string()
>       )
>          )
>     "/>
>
>     <xsl:sequence select=
>      "for $lastReplIndex in $actualIndexes[last()],
>           $last-replacedText in $vPatterns[starts-with(substring($pText,
> $lastReplIndex), old)][1]/old,
>           $lastReplacementLength in string-length($last-replacedText)
>        return
>           substring($pText, $lastReplIndex + $lastReplacementLength)
>      "/>
>       </xsl:variable>
>
>       <xsl:sequence select="string-join($vResultSequence, '')"/>
>   </xsl:function>
> </xsl:stylesheet>
>
> When this transformation is applied on this source XML document:
>
> <t>a corelation between a quick brown fox and a dog</t>
>
> the wanted result is produced:
>
> *a dependency between a slow white elephant and a dog*
>
>
>
> Cheers,
> Dimitre
>
>
> On Thu, May 16, 2019 at 12:49 PM Dimitre Novatchev dnovatchev@xxxxxxxxx <
> xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
>> https://stackoverflow.com/a/5283744/36305
>>
>> Cheers,
>> Dimitre
>>
>> On Thu, May 16, 2019 at 11:59 AM Rick Quatro rick@xxxxxxxxxxxxxx <
>> xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>>
>>> Hi,
>>>
>>>
>>>
>>> I have a look up file of find/change pairs that I have to apply to a
>>> text node in my XML document. I am using XSLT 2. Here is an example of the
>>> lookup file:
>>>
>>>
>>>
>>> <?xml version="1.0" encoding="UTF-8"?>
>>> <findchange_lookup>
>>>     <findchange find="Eicas" change="EICAS"/>
>>>     <findchange find="Ulb" change="ULB"/>
>>> </findchange_lookup>
>>>
>>> I am reading this in as a global variable, but I am not sure the best
>>> approach for doing multiple replacements on the node. I can use recursion
>>> like in XSLT 1, but I can't think of how to do this in XSLT 2. There could
>>> be any number of <findchange> elements in my lookup file. Any pointers
>>> would be appreciated. Thank you very much.
>>>
>>>
>>>
>>> Rick
>>>
>>>
>>>
>>> Rick Quatro
>>>
>>> Carmen Publishing Inc.
>>>
>>> rick@xxxxxxxxxxxxxxx
>>>
>>> 585-729-6746
>>>
>>> www.frameexpert.com/store/
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>>
>>> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
>>> EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/782854> (by
>>> email)
>>>
>>
>>
>> XSL-List info and archive <http://www.mulberrytech.com/xsl/xsl-list>
>> EasyUnsubscribe <http://lists.mulberrytech.com/unsub/xsl-list/782854> (by
>> email <>)

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.