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

Subject: RE: [xsl] Copying parent nodes with different selection of their content
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Wed, 25 Apr 2007 16:13:50 +0100
Perhaps something like this:

<xsl:for-each select="Document/*[starts-with(name(), 'Make-Toute-Seul')]"/>
  <Document>
    <xsl:copy-of select="../* except ."/>
  </Document>
</xsl:for-each>

Michael Kay
http://www.saxonica.com/ 

> -----Original Message-----
> From: Abel Braaksma [mailto:abel.online@xxxxxxxxx] 
> Sent: 25 April 2007 15:53
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject: [xsl] Copying parent nodes with different selection 
> of their content
> 
> 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