xsl-list
[Top] [All Lists]

Re: [xsl] Copying nested tags and adding attributes

2007-01-30 02:32:52
graeme(_dot_)ludwig(_at_)bt(_dot_)com wrote:
<description>See how <b>cans</b> are made into model cars, planes, bikes, etc. at  <a 
href="http://www.tincanmodels.com/"; target="_self">Tin Can Models</a>.
</description>
and transform it into See how <b>cans</b> are made into model cars, planes, bikes, etc. at <a href="http://www.tincanmodels.com/"; alt="Tin Can Models" target="_self">Tin Can Models</a>. i.e. I want to add an alt attribute to the hyperlink and set it to the text of the link itself. The bold attribute should remain unchanged. <xsl:template match="description">
  <xsl:copy-of select="node()"/>
</xsl:template>
('bold' is not an attribute, but a node)

If you want to do a copy and you want to change some things, the best method to use is the identity template, or copying template. Sel Mangano in his "XSLT Cookbook" calls this technique the "Overriding Copy Idiom" (chapter "XML to XML").

The trick is simple, but when beginning with XSLT a little confusing: you create a "rule" (in xslt terms: a template) that makes a shallow copy of the current node and applies all templates for all children nodes. In XSLT, only the most specific rule is used, which makes it easy to override (that's why 'Overriding Copy Idiom') this general rule with more specific ones.

The general template looks like this:

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

This template has been thoroughly discussed several times in the archive, so I leave it to this for now. Note the difference between "copy-of" and "copy". The first copies everything, including all children, and *does not* let you override anything. The second only copies the current node and gives you the option to do whatever you want with it (like adding children like attributes, texts, other nodes whatever).

After you have added the above template, all you need to do is adding specific templates. In your case, you seem to want to remove the 'description' node (well, the tag, as you may put it) but you want to keep its children:

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

Run it with only these two and watch the effect. Note the absence of "xsl:copy". Next, you'd like to change the 'a'-node, in particular, you want to add an attribute 'alt' to the 'a'-node. This can be done in several ways, I show you one:

<xsl:template match="a">
   <xsl:copy>
<xsl:attribute name="alt"><xsl:value-of select="." /></xsl:attribute>
       <xsl:apply-templates select="@* | node()" />
   </xsl:copy>
</xsl:template>

Run it, with only this and the copy template and watch the effect. Its intent is to copy itself ('a'), add an attribute, and then add the children (the text, the attributes). Note that it will give a dynamic error if you place xsl:attribute after the xsl:apply-templates. This is because attributes must be created before any children of a node are created (the child is here: the text of the 'a' node).

If you place all templates inside a stylesheet (order is not important), and run it with your source, you will get the desired result, because the XSLT processor will automatically choose the matching templates for 'a' and 'description' when it encounters them in the source tree.



to get the text out as per solution 12, but am unsure how to generate the extra alt attribute for any <a> elements that occur within the text. I believe I am using an XSLT 1.0 processor.

If you are unsure, run the following stylesheet, it will print the version for you (also see the List Guidelines at MulberryTech's):

<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:output method="text"/>

   <xsl:template match="/">
       <xsl:text>My XSLT Version: </xsl:text>
       <xsl:value-of select="system-property('xsl:version')"/>
   </xsl:template>
</xsl:stylesheet>


The output will look like:

My XSLT Version: 1.0



Cheers,
-- Abel Braaksma
  http://www.nuntia.nl

--~------------------------------------------------------------------
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>