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: Second try: Search and replace many strings that may not be present in target



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


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