Re: [xsl] Identity transform on node-set loaded with document()

Subject: Re: [xsl] Identity transform on node-set loaded with document()
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Thu, 02 Aug 2007 11:19:22 +0200
Matt Poff wrote:
Hi,

I've been away from XSLT a while and am stumbling on how to implement the following:

Welcome back to XSLT ;)



My transform imports, using document(), an HTML snippet contain a populated <head></head> tag. I want to copy this into one of several result trees I am outputting as is *except* the <title/> tag needs to be populated with a value.


Initially I created a named template and sent the loaded node-set to it, then realised I probably needed an identity transform but all of the identity transform examples I've found seem to be set-up to operate on the master document only. What's the best way to carry out this task? Can I do an identity transform with a named template?

I'm sure there's a fairly simple solution but it's passing me by.


If you mean that your matching templates are currently triggered by both the principal source document and the sources requested via document('xxx') you can use a mode in both the templates and the apply-template that have to deal with document('xxx'). In XSLT 2.0 you can combine rules for several modes (if they are they same) by using a combination of mode="#all" in the matching template, mode="#current" in the contained apply-templates and your new mode="newtitle" in your specific apply-template (where you call your document). I.e., the following code shares the copy template for both your principal source and your secondary source document:


<xsl:template match="/">
  <xsl:apply-templates select="document('xyz')" mode="newtitle" />
  <xsl:apply-templates select="*" />
</xsl:template>

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

<xsl:template match="title" mode="newtitle">
    <title>a new title</title>
</xsl:template>


If you are stuck with XSLT 1.0 you cannot share the templates this way and you need to create one copy template for each mode.


Other options for distinguishing between the two node trees can be based on unique properties, i.e., the namespace or a specific pattern, but these methods are more of a hassle, usually. And yes, you can also do it with call-template, for-each etc, but then you need much more instructions and logic. Let XSLT do the job for you with apply-templates/matching templates is often the easiest approach.

Cheers,
-- Abel Braaksma

Current Thread