RE: [xsl] Displaying element value in browser, which is inside CDATA in XML

Subject: RE: [xsl] Displaying element value in browser, which is inside CDATA in XML
From: Liam R E Quin <liam@xxxxxx>
Date: Mon, 18 Jul 2011 08:51:47 -0400
On Mon, 2011-07-18 at 17:31 +0530, Ramkumar V wrote:

> XSL:
> ====
> <xsl:template match="bk:text">
>  <p><xsl:value-of select="." disable-output-escaping="yes"/></p>
> </xsl:template>
> 
> <xsl:template match="a">
> <xsl:apply-templates/><sup><font color="red"><xsl:value-of
> select="@name"/></font></sup>
> </xsl:template>

Let's simplify this to wanting
   <span class="page"><xsl:value-of select="@name"/></span>
in place of <a>...</a>

Now, you don't have any "a" elements in your input, so your template
won't ever match, because they are in CDATA sections.  Even if you did
have "a" elements, you don't call apply-templates in your template for
bk:text, so the template to match "a" would never get used.

If it helps, the meaning of "value-of" is, "take the string value of the
expression I give you, ignoring, any markup you find, just taking the
text content" and since you want to get at markup, value-of is clearly
not what you want.

Back to your actual XML input and the CDATA section...

My general rule is that 99% of the time people use CDATA sections, they
shouldn't, and for sure that's such a case here. If you can remove the
CDATA section markup and leave the content things will work as you
expect, once you use apply-templates instead of xsl:value-of select=".".

If you're using CDATA so you don't need to escape > note that you *do*
need to escape ]]>, e.g. as ]]]>]<!CDATA[> (if this is a Web
application, not escaping ]]> can leave your site vulnerable to CDATA
injection attacks of course).

Your example has "individual&#8217;s" presumably with the asusmption
that &#8217; represents an apostrophe. It doesn't, because the & is not
special inside a CDATA section [1].

If not, you can use replace() in XSLT 2, or, if you are still on XSLT 1
you can use exslt.org's replace...

You need somthing like
    <xsl:template match="bk:text/text()">
      <xsl:value-of select="replace(.,
          '&lt;a name=&quot;([^&quot;]*)&quot;&gt;.*&lt;/a&gt;',
          '&lt;span class=&quot;page&quot;>$1&lt;/span>')"
          disable-output-escaping="yes"/>
    </xsl:template>
> 
    <xsl:match select="bk:text">
       <p><xsl:apply-templates/></p>
    </xsl:match>

You'll need to tweak the regular expression - probably you'll need 
something like

'&lt;a [^&gt;]*name *= *&quot;([^&quot;]*)&quot;[^&gt;]*&gt;&lt;/a&gt;',

which without the quoting is,

  <a [^>]*name *= *"([^"]*)"[^>]*>[^>]*</a>

This way you don't need an extension. However, if you are running this
in a Web browser, you have only access to XSLT 1, and you would have to
use string processing with substring-before() and so on.

You'd need to tell us more about your exact environment to get more
specific help I expect. But maybe this will get you started.

Liam

-- 
Liam Quin - XML Activity Lead, W3C, http://www.w3.org/People/Quin/
Pictures from old books: http://fromoldbooks.org/

Current Thread