RE: [xsl] Selecting everything "before" and "after" a specific node

Subject: RE: [xsl] Selecting everything "before" and "after" a specific node
From: "Harvey, Paul" <Paul_Harvey@xxxxxxxxxxx>
Date: Thu, 2 Apr 2009 11:36:04 -0400
Thanks so much for this and other folks suggestions!
I'll be trying them out (and learning a ton in the process).

-----Original Message-----
From: Martin Honnen [mailto:Martin.Honnen@xxxxxx]
Sent: Thursday, April 02, 2009 7:52 AM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Selecting everything "before" and "after" a specific
node

Paul Harvey wrote:
> Hi,
> I've searched and posted on another list, but have not found an answer
to this problem...
> I have XML like this...
>
> <A i="1">
>       <B i="2">
>             <C i="3"/>
>       </B>
>       <B i="4">
>             <C i="5">
>                   <D i="6"/>
>                   <D i="7">
>                         <E i="8"/>
>                         <E i="9" msg="get me out of here!"/>
>                         <E i="10"/>
>                   </D>
>                   <D i="11"/>
>             </C>
>             <C i="12"/>
>       </B>
> </A>
> And I need to break it out into 3 nodesets, delimited by the <E i="9"
msg="get me out of here!"/> such that I'd end up with...
> <ROOT>
>        <BEFORE>
>         <A i="1">
>                   <B i="2">
>                         <C i="3"/>
>                   </B>
>                   <B i="4">
>                         <C i="5">
>                               <D i="6"/>
>                               <D i="7">
>                                     <E i="8"/>
>                               </D>
>                         </C>>
>                   </B>
>         </A>
>        </BEFORE>
>        <PULLED_OUT>
>             <E id="9" msg="get me out of here!"/>
>        </PULLED_OUT>
>        <AFTER>
>         <A i="1">
>                   <B i="4">
>                         <C i="5">
>                               <D i="7">
>                                     <E i="10"/>
>                               </D>
>                               <D i="11"/>
>                         </C>
>                         <C i="12"/>
>                   </B>
>         </A>
>        </AFTER>
> </ROOT>
>
> Any suggestions as to how I'd go about that?

Here is an attempt with XSLT 2.0:

<xsl:stylesheet
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
   version="2.0">

   <xsl:output method="xml" indent="yes"/>
   <xsl:strip-space elements="*"/>

   <xsl:variable name="pn" select="//*[@i = '9']"/>

   <xsl:template match="/">
     <ROOT>
       <BEFORE>
         <xsl:apply-templates select="*" mode="before"/>
       </BEFORE>
       <PULLED_OUT>
         <xsl:copy-of select="$pn"/>
       </PULLED_OUT>
       <AFTER>
         <xsl:apply-templates select="*" mode="after"/>
       </AFTER>
     </ROOT>
   </xsl:template>

   <xsl:template match="*[. &gt;&gt; $pn or . is $pn]" mode="before"/>

   <xsl:template match="*[. is $pn or empty(. intersect $pn/ancestor::*)

and empty(. intersect $pn/following-sibling::*)]" mode="after"/>

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

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

   <xsl:template match="@* | text() | comment() |
processing-instruction()" mode="after before">
     <xsl:copy/>
   </xsl:template>

</xsl:stylesheet>


--

	Martin Honnen
	http://JavaScript.FAQTs.com/

Current Thread