xsl-list
[Top] [All Lists]

Re: [xsl] recursive replacing strings with nodes

2010-02-19 05:58:17
James Cummings wrote:
Ok, I've been beating my brains out against this one for awhile trying
recursive analyze-string and replace() techniques in XSLT2 but just
can't get it to do what I want.

Let's say I have some input like:
====
    <root>
        <ab type="foo">
            <seg>abc def abc+def</seg><lb/>
            <seg>+def abcdef foo+def=blah</seg><lb/>
            <seg>foo+def=blah</seg>
        </ab>
        <ab type="foo">
            <seg>ab de ac+def</seg><lb/>
            <seg>+cdef abdef foo+def=blah</seg><lb/>
            <seg>foo+cdef=blah</seg>
        </ab>
    </root>
====

What I want to do is go through a lookup table of replacements for
certain strings in the text of the seg elements.  The replacements are
stored something like:

====
 <root>
    <choice>
        <abbr>abc</abbr>
        <expan>
            <w>ab<m>c</m></w>
        </expan>
    </choice>
        <choice>
            <abbr>foo+def=blah</abbr>
            <expan>
                <w>foo<m>def</m></w><w type="erg">blah</w>
            </expan>
        </choice>
        <choice>
        <abbr>+def</abbr>
        <expan>
            <w>de<m>f</m></w>
        </expan>
    </choice>
    </root>
 ====

Here is a stylesheet trying to solve that

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
  version="2.0"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema";
  xmlns:mf="http://example.com/2010/mf";
  xmlns:functx="http://www.functx.com";
  exclude-result-prefixes="xsd mf functx">

  <xsl:function name="functx:escape-for-regex" as="xsd:string"
                 >
    <xsl:param name="arg" as="xsd:string?"/>

    <xsl:sequence select="
     replace($arg,
             '(\.|\[|\]|\\|\||\-|\^|\$|\?|\*|\+|\{|\}|\(|\))','\\$1')
   "/>

  </xsl:function>


<xsl:param name="abbr-url" as="xsd:string" select="'test2010021902.xml'"/> <xsl:variable name="abbr" as="element(abbr)*" select="doc($abbr-url)/root/choice/abbr"/>

  <xsl:function name="mf:replace" as="node()*">
    <xsl:param name="str" as="xsd:string"/>
    <xsl:param name="abbr" as="element(abbr)*"/>
    <xsl:choose>
      <xsl:when test="$abbr">
<xsl:analyze-string select="$str" regex="{functx:escape-for-regex($abbr[1])}">
          <xsl:matching-substring>
            <xsl:copy-of select="$abbr[1]/../expan/w"/>
          </xsl:matching-substring>
          <xsl:non-matching-substring>
            <xsl:sequence select="mf:replace(., $abbr[position() gt 1])"/>
          </xsl:non-matching-substring>
        </xsl:analyze-string>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$str"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:function>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@*, node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="seg">
    <xsl:copy>
      <xsl:sequence select="mf:replace(., $abbr)"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>


--

        Martin Honnen
        http://msmvps.com/blogs/martin_honnen/

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>