Steve Muench
Transformations of this sort are best done as a variation
on the identity transformation.
If you put the following handy identity transformation
into a file like "identity.xsl"...
<!-- The Identity Transformation -->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Whenever you match any node or any attribute -->
<xsl:template match="node()|@*">
<!-- Copy the current node -->
<xsl:copy>
<!-- Including any attributes it has and any child nodes -->
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
And then build a stylesheet that imports the "identity.xsl"
stylesheet as part of it as the one does below, then whatever
templates you put in this stylesheet will take precedence
over the base (imported) template that is doing the identity
transformation of each node. The result is that the tree gets
copied verbatim, with the exception of the "overrides" your
templates below pick up...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- Import the identity transformation. -->
<xsl:import href="Identity.xsl"/>
<!--
| This will match any element's "date" attribute
| Make the pattern more specific if this is not appropriate
+-->
<xsl:template match="@date">
<!-- This will construct a "date" attribute having value of its content -->
<xsl:attribute name="date">
<!-- Change what's in here to construct the "new" date format -->
<xsl:value-of select="concat('new',.)"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
This will transform a document like:
<a date="1">
<b date="2"/>
<c>
<d date="3"/>
</c>
</a>
into:
<a date="new1">
<b date="new2"/>
<c>
<d date="new3"/>
</c>
</a>
Jeni Tennison offers
You want to create copies of most nodes. The 'copy me, but pay
attention to my contents' templates look like:
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates />
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:copy-of select="." />
</xsl:template>
[Uses the built-in templates to get to the document element and to copy the
value of any text nodes. I haven't included copying processing
instructions etc. here.]
These templates are very general - they don't give names to match on or use
predicates - so they're given low priority. Any template that you have
that *does* use a name or a predicate will be applied in preference. So,
for your exception, do:
<xsl:template match="@date[. = 'some format']">
<xsl:attribute name="date">some new format</xsl:attribute>
</xsl:template>
This will make any date attribute with a value of 'some format' be changed
into a date attribute with a value of 'some new format'. If there are any
other restrictions on what the date should be (like what element it's an
attribute on), you can put them in the match pattern as well.
|