[xsl] Copying parent nodes with different selection of their content

Subject: [xsl] Copying parent nodes with different selection of their content
From: Abel Braaksma <abel.online@xxxxxxxxx>
Date: Wed, 25 Apr 2007 16:52:59 +0200
Hi List,

This should be a really easy thing to do, I'm sure, but I'm having a blank spot today when it comes to XSLT, it seems. Perhaps some imperative twist in my mind stops me from writing down a straight solution (or I just never encountered the problem before, but I couldn't find it in my own archive).

Basically, I have the solution, but it is so awkward that I am sure that "there is a better way", esp. with XSLT. Take the dataset (see variable $copy-me in the XSLT sample) and consider a copy of the Document node for each Make-Toute-Seul-X node, without the other Make-Toute-Seul-X nodes. The result of the transformation is this (see the similar data, with changing Make-Toute-Seul-X elements):

(The original data is a SOAP envelope, and the envelope needs to be copied a couple of times for each occurrence of some node, which triggers a document in 'real' life)

OUTPUT:
<Header>
   <Meta/>
</Header>
<Body>
   <Document>
       <Preceding-1/>
       <Preceding-2/>
       <Make-Toute-Seul-1/>
       <Following-1/>
       <Following-2/>
   </Document>
   <Document>
       <Preceding-1/>
       <Preceding-2/>
       <Make-Toute-Seul-2/>
       <Following-1/>
       <Following-2/>
   </Document>
   <Document>
       <Preceding-1/>
       <Preceding-2/>
       <Make-Toute-Seul-3/>
       <Following-1/>
       <Following-2/>
   </Document>
</Body>



The XSLT looks like this and can be run on itself (I had other incarnations, equally bad, anybody with a nicer solution that feels more like 'XSLT'?). I'd like to move the duplicated logic about the nodes Make-Toute-Seul-X to a single location, to make maintenance a breeze.


<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="2.0">
<xsl:output indent="yes" />
<xsl:variable name="copy-me">
<Header>
<Meta />
</Header>
<Body>
<Document>
<Preceding-1 />
<Preceding-2 />
<Make-Toute-Seul-1 />
<Make-Toute-Seul-2 />
<Make-Toute-Seul-3 />
<Following-1 />
<Following-2 />
</Document>
</Body>
</xsl:variable>
<xsl:template match="/">
<xsl:apply-templates select="$copy-me/*"/>
</xsl:template>
<xsl:template match="Body">
<xsl:copy>
<xsl:apply-templates select="*[Make-Toute-Seul-1]" >
<xsl:with-param name="seul" select="*/Make-Toute-Seul-1" tunnel="yes" />
</xsl:apply-templates>
<xsl:apply-templates select="*[Make-Toute-Seul-2]" >
<xsl:with-param name="seul" select="*/Make-Toute-Seul-2" tunnel="yes" />
</xsl:apply-templates>
<xsl:apply-templates select="*[Make-Toute-Seul-3]" >
<xsl:with-param name="seul" select="*/Make-Toute-Seul-3" tunnel="yes" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="Document">
<xsl:param name="seul" tunnel="yes"/>
<xsl:copy>
<xsl:copy-of select="$seul/preceding-sibling::*[not(self::Make-Toute-Seul-1 | self::Make-Toute-Seul-2 | self::Make-Toute-Seul-3)]" />
<xsl:copy-of select="$seul" />
<xsl:copy-of select="$seul/following-sibling::*[not(self::Make-Toute-Seul-1 | self::Make-Toute-Seul-2 | self::Make-Toute-Seul-3)]" />
</xsl:copy>
</xsl:template>
<xsl:template match="* | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>





Thanks for any help,


Cheers,

Abel

Current Thread