Rick Livesey wrote:
I realise that the 'disable-output-escaping' method is a hack, but since
my tags are conditional I'm not sure how to get around this but there
must be a better solution out there and as an XSLT beginner, I'm a bit
stumped.
Can anyone point me in the right direction?
d-o-e is never a good idea, especially not when in XSLT 2.0. Tokenizing
styles is, I believe, best achieved using a simple micro-pipeline. Hmm,
I wanted to give you a simple enough example, but then I went on
generalizing it a bit and it became rather complex. I'm not sure of your
skill level, but I am happy to talk you through the following stylesheet
if necessary. Here are some pointers:
This example template assumes $input with 'span' elements and only text
therein, but it is build with expansion in mind, so it won't be too hard
to make it work with nodes inside 'span'.
The idea I had was this: make one place and one place only where you
provide your stylesheet with a mapping from CSS to XML (or HTML,
whichever you prefer). The example is rather basic, but is should get
you going. Just change the global $css-mapping variable to your liking
and you are done (you can use the placeholder [value] in any attribute,
see font-family). All you need to do is add the literal nodes there.
What it does is using your input span elements and some
matching/micro-pipelining/tunneling/tokenizing/more micro-pipelining to
create hierarchical XML from a tokenizable string (the css). The mode
switching is not strictly necessary and perhaps rather expensive, but I
find it clearer this way.
Enjoy!
Cheers,
-- Abel Braaksma
(I am sure the mailer will mess up my stylesheet big time... I hope
it'll be a bit readable when archived...)
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes" />
<xsl:variable name="input">
<span style="font-weight:bold;font-family:times new
roman;text-decoration:underline">Some text</span>
<span
style="font-weight:normal;font-family:arial;text-decoration:none">Some
other text</span>
<span style="font-weight:bolder;">Bolder text</span>
</xsl:variable>
<xsl:variable name="css-mapping">
<css property="font-weight" value="bold"><b /></css>
<css property="font-weight" value="bolder"><b /></css>
<css property="font-family"><font name="[value]" /></css>
<css property="font-weight" value="normal"><span /></css>
<css property="text-decoration" value="none"><span /></css>
<css property="text-decoration" value="underline"><u /></css>
</xsl:variable>
<xsl:template match="/">
<xsl:apply-templates select="$input/*" />
</xsl:template>
<xsl:template match="span">
<xsl:variable name="css">
<xsl:apply-templates select="@style" >
<xsl:with-param name="text" tunnel="yes" select="text()" />
</xsl:apply-templates>
</xsl:variable>
<xsl:copy-of select="$css"></xsl:copy-of>
</xsl:template>
<!-- the core: dissecting the @style attribute -->
<xsl:template match="@style">
<xsl:variable name="flat-css">
<xsl:for-each select="tokenize(., ';')">
<!-- prop/value pair of css attribute -->
<xsl:variable name="property" select="tokenize(.,
':')[1]" />
<xsl:variable name="value" select="tokenize(., ':')[2]" />
<!-- apply for valued selection -->
<xsl:apply-templates select="
$css-mapping/css
[(_at_)property = $property]
[(_at_)value = $value]/*" mode="css" />
<!-- apply for fill-in selection -->
<xsl:apply-templates select="
$css-mapping/css
[(_at_)property = $property]
[not(@value)]/*" mode="css" >
<xsl:with-param name="value"
select="tokenize(., ':')[2]"
tunnel="yes" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:variable>
<!-- go from flat css to hierarchical -->
<xsl:apply-templates select="$flat-css/*[1]" mode="flat-to-hier"/>
</xsl:template>
<!-- simple treewalker template to go from flat to hierarchical -->
<xsl:template match="*" mode="flat-to-hier">
<xsl:param name="text" tunnel="yes" />
<xsl:copy>
<xsl:apply-templates select="following-sibling::*[1]"
mode="#current"/>
<xsl:sequence select="if(following-sibling::*) then '' else
$text" />
</xsl:copy>
</xsl:template>
<xsl:template match="* | @*" mode="css">
<xsl:copy>
<xsl:apply-templates select="* | @*" mode="#current" />
</xsl:copy>
</xsl:template>
<xsl:template match="@*[. = '[value]']" mode="css">
<xsl:param name="value" tunnel="yes" select="''"/>
<xsl:attribute name="{name()}" select="$value" />
</xsl:template>
</xsl:stylesheet>
--~------------------------------------------------------------------
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>
--~--