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

RE: Second try: Search and replace many strings that m

Subject: RE: Second try: Search and replace many strings that may not be present in target
From: "Andrew Welch" <awelch@xxxxxxxxxxxxxxx>
Date: Mon, 20 May 2002 16:17:50 +0100
rtf xsl
Zack,

Your post is fairly difficult to read (like mine usually...) so its hard
to understand what you are actually after.  Its normally best to post a
sample of your data, a sample of the output required and a list of any
things important to the transformation.

Anyway, I think you should be able to do what you want without using two
passes.

You should build a result-tree-fragment of all the <quote> elements:

<xsl:variable name="quotes-rtf">
  <xsl:for-each select="//quote">
    <quote who="{@who}"/>
  </xsl:for-each>
</xsl:variable>

And convert that to a node-set using the node-set extension function of
your processor (in this case msxml4)

<xsl:variable name="quotes" select="msxsl:node-set($quotes-rtf)"/>

Then you should check each text() node to see if it contains any of the
@who's in the rtf we have just created.  The way I have done this is to
use a recursive template that will test against each of the @who's.


<xsl:template match="text()">
  <xsl:call-template name="checkForName">
    <xsl:with-param name="theText" select="."/>
  </xsl:call-template>
</xsl:template>


<xsl:template name="checkForName">
  <xsl:param name="theText" select="notext"/>
  <xsl:param name="position" select="1"/>
  <xsl:variable name="who" select="$quotes/quote[$position]/@who"/>
  <xsl:choose>
    <xsl:when test="3 > $position">
    <xsl:choose>
    <xsl:when test="contains($theText,$who)">
    <xsl:value-of select="substring-before($theText,$who)"/>
        <span id="quoteLink"><xsl:value-of select="$who"/></span>
      <xsl:value-of select="substring-after($theText,$who)"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="checkForName">
        <xsl:with-param name="theText" select="$theText"/>
        <xsl:with-param name="position" select="$position + 1"/>
      </xsl:call-template>
    </xsl:otherwise>
    </xsl:choose>
  </xsl:when>
  <xsl:otherwise><xsl:value-of select="."/></xsl:otherwise>
  </xsl:choose>
</xsl:template>


If it has a match it will output the text a span wrapping the name:
 
  <span id="quoteLink"><xsl:value-of select="$who"/></span>
     
Ive called this quoteLink, but you can call it something better...  To
only have the first occurance as a link, I would use a bit of javascript
called by the onload event.  If you create an array of elements with id
quoteLink you can convert the [0] item to the html you need. 

Im not too sure how this solution would work across multiple documents,
but Im sure someone will be able to help.  You will only need to adjust
the quotes-rtf to accomodate it, such as:

<xsl:variable name="quotes-rtf">
  <xsl:for-each select="$doc1//quote">
    <quote who="{@who}"/>
  </xsl:for-each>
  <xsl:for-each select="$doc2//quote">
    <quote who="{@who}"/>
  </xsl:for-each>
</xsl:variable>

Anyway, I hope all this helps,

cheers
andrew

=====full stylesheet=======
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                version="1.0">

<xsl:variable name="quotes-rtf">
  <xsl:for-each select="//quote">
    <quote who="{@who}"/>
  </xsl:for-each>
</xsl:variable>

<xsl:variable name="quotes" select="msxsl:node-set($quotes-rtf)"/>

<xsl:template match="/">
  <xsl:apply-templates/>
</xsl:template>


<xsl:template name="checkForName">
  <xsl:param name="theText" select="notext"/>
  <xsl:param name="position" select="1"/>
  <xsl:variable name="who" select="$quotes/quote[$position]/@who"/>
  <xsl:choose>
    <xsl:when test="3 > $position">
    <xsl:choose>
    <xsl:when test="contains($theText,$who)">
    <xsl:value-of select="substring-before($theText,$who)"/>
        <span id="quoteLink"><xsl:value-of select="$who"/></span>
      <xsl:value-of select="substring-after($theText,$who)"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="checkForName">
        <xsl:with-param name="theText" select="$theText"/>
        <xsl:with-param name="position" select="$position + 1"/>
      </xsl:call-template>
    </xsl:otherwise>
    </xsl:choose>
  </xsl:when>
  <xsl:otherwise><xsl:value-of select="."/></xsl:otherwise>
  </xsl:choose>
</xsl:template>


<xsl:template match="text()">
  <xsl:call-template name="checkForName">
    <xsl:with-param name="theText" select="."/>
  </xsl:call-template>
</xsl:template>

<xsl:template match="section">
  <xsl:apply-templates select="text()"/>
</xsl:template>

</xsl:stylesheet>

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.350 / Virus Database: 196 - Release Date: 17/04/2002
 

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


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.