Re: [xsl] Matching and changing attributes.

Subject: Re: [xsl] Matching and changing attributes.
From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
Date: Wed, 30 May 2001 14:09:39 +0100
At 06:24 PM 5/30/01, Thorbjørn wrote:
I have a situtation where I would like add a few rules to clean up an
XHTML-document which uses too many @class attributes.

Cool. As you've probably already figured out, such transforms are often easily written as variants or extensions to the step-by-step identity transform (the one given in the spec, XSLT 7.5):


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

I know that I can match a node with a class-attribute with a specific text,
but this means that other rules cannot come in play with that node, and it
would be most intuitive to work on the attribute level.

So my question is,

Given a node with a class attribute, like

<mynode class="somestring"/>

how do I write a template that is fired when <xsl:apply-templates
match="@*"> is executed,  and optionally change the attribute giving the
result

<mynode class="someotherstring">

You mean <xsl:apply-templates select="@*"/> ^^^^^^ Or its variant (as in the identity transform)

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

which selects all child nodes (node()) and all attribute nodes (@*) for processing.

By default, an attribute, once selected, will match the built-in template

<xsl:template match="@*">
  <xsl:value-of select="."/>
</xsl:template>

which is no good to you -- you don't want the attribute's value simply copied (without the attribute itself). The identity transform's template, containing

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

is much closer. Note that in the case of attributes, there are no attributes or child nodes, so the apply-templates inside the xsl:copy does nothing. But the attribute itself gets copied (not just its value but the whole node).

Now this would work; except sometimes you don't want to copy. (When? when your attribute is a 'class' attribute with certain unacceptable values.) So you write a specialized template for those cases:

<xsl:template match="@class">
  <xsl:attribute name="class">
    <xsl:choose>
       <xsl:when test=".='badvalue'">
         <xsl:text>goodvalue</xsl:text>
       </xsl:when>
       <xsl:when test=".='otherbadvalue'">
         <xsl:text>othergoodvalue</xsl:text>
       </xsl:when>
       <xsl:otherwise>
         <xsl:value-of select="."/>
       </xsl:otherwise>
    </xsl:choose>
  </xsl:attribute>
</xsl:template>

[Note also it's easy to enhance this. So the test

       <xsl:when test=".='badvalue'">
         <xsl:value-of select="local-name(..)"/>
       </xsl:when>

would take the (local) name of the attribute's parent element and pop that on the class attribute.]

If your stylesheet also includes the identity transform template (which, you remember, simply copies each node one by one down the tree), it will still fire this template for any 'class' attribute, because its priority is higher than that of the identity transform's match="@*". For all other nodes, it will just copy them over to the result.

Is that something like what you want? The basic trick is to make sure you are applying templates on the attribute axis (something that doesn't happen by default), and then to match="@class" and create the replacement attribute the way you want it in that template.

(PS:  If anyone can point me to a page about how to use both this list and
Outlook while keeping my sanity, I will appreciate it).

I wish I could. I don't like what Eudora does either. It's that confounded "support" for HTML, which mangles and hides stuff. I think Eudora is trying to match features with Outlook. What, it never occurred to those engineers that people would want to write about code in their e-mail? (Eudora won't parse HTML if the line doesn't lead off with the code. Maybe Outlook is the same.)


Good luck,
Wendell



======================================================================
Wendell Piez                            mailto:wapiez@xxxxxxxxxxxxxxxx
Mulberry Technologies, Inc.                http://www.mulberrytech.com
17 West Jefferson Street                    Direct Phone: 301/315-9635
Suite 207                                          Phone: 301/315-9631
Rockville, MD  20850                                 Fax: 301/315-8285
----------------------------------------------------------------------
  Mulberry Technologies: A Consultancy Specializing in SGML and XML
======================================================================


XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list



Current Thread