Vito
Vito

Reputation: 1201

Modify "on the fly" the portal column content tag's class

I need to modify "on the fly" a class name in portal-column-content tag, this is the html code rendered:

<div id="portal-column-content" class="cell width-9 position-1:4">

I want to replace only "width-9" with "width-12".
Any advice?
Thank's
Vito

Upvotes: 1

Views: 322

Answers (3)

SteveM
SteveM

Reputation: 6048

Since you've tagged this with "diazo", the simplest solution is probably to use diazo rules. Just use a replace, before or after rule to copy content children of #portal-column-content to the theme children of a correctly classed #portal-column-content.

Use an "if" expression if it's to be done selectively.

Upvotes: 0

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243459

This XSLT 1.0 transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

 <xsl:template match="div[@id='portal-column-content']/@class">
  <xsl:attribute name="class">
   <xsl:value-of select=
    "substring-before(concat(.,'width-9'), 'width-9')"/>
   <xsl:value-of select="'width-12'"/>
   <xsl:value-of select="substring-after(., 'width-9')"/>
  </xsl:attribute>
 </xsl:template>
</xsl:stylesheet>

when applied on the following sample XML document:

<html>
    <div id="a" class="a"/>
    <div id="b" class="b"/>
    <div id="c" class="cell width-9 position-1:4"/>
    <div id="portal-column-content" class="cell width-9 position-1:4"/>
    <div id="d" class="d"/>
    <div id="e" class="cell width-9 position-1:4"/>
</html>

produces the wanted, correct result (only replaced is the 'width-9' substring of the class attribute of any div that has id attribute with string value 'portal-column-content':

<html>
   <div id="a" class="a"></div>
   <div id="b" class="b"></div>
   <div id="c" class="cell width-9 position-1:4"></div>
   <div id="portal-column-content" class="cell width-12 position-1:4"></div>
   <div id="d" class="d"></div>
   <div id="e" class="cell width-9 position-1:4"></div>
</html>

Do note:

  1. Only replaced is the 'width-9' substring of the class attribute of any div that has id attribute with string value 'portal-column-content'. Other div elements that have a different id attribute aren't affected.

  2. The transformation correctly works with class attributes, whose string value doesn't contain 'width-9' -- compare with the other answer, whose XSLT solution in such case completely replaces the string value of the class attribute with 'width-12'.

Upvotes: 1

jos
jos

Reputation: 823

Since you ask for advise, here is some:

  1. Do not use a css class to signify anything concrete, let it signify intent. The concrete implementation of the intent comes in the css. For instance, do not create a class named width-9, rather create one named portal-column-content. You can then make portal-column-content be width:9px, width:12em or whatever.

  2. Doing a string-replace like this is not really a thing you would do with xslt. Even though you could. Depending on your setup there are other, better ways.

  3. If you can't/won't follow any of the above advise, try

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="@class">
            <xsl:attribute name="class">
            <xsl:value-of select="substring-before(.,'width-9')"/>width-12<xsl:value-of select="substring-after(.,'width-9')"/>
            </xsl:attribute>
        </xsl:template>
    </xsl:stylesheet>
    

Upvotes: 2

Related Questions