Re: XSL: Returning a selected node in the context of it's ancestors

Subject: Re: XSL: Returning a selected node in the context of it's ancestors
From: "Clark C. Evans" <clark.evans@xxxxxxxxxxxxxxxxxxxx>
Date: Tue, 19 Oct 1999 17:29:01 -0400 (EDT)
On Tue, 19 Oct 1999, James Carlyle wrote:
> Has anyone tried to use XSL to return a document fragment that includes the
> necessary parent nodes for a selected node, so that the lineage of the
> selected node is maintained?  

 <snip/>
 
> <vendor name="james">
>  <product id="1234">
>   <material>SiO2</material>
>  </product>
>  <product id="5678">
>   <material>CO2</material>
>  </product>
> </vendor>
> 
> and a stylesheet fragment
> 
> <xsl:for-each select="/vendor/product/material[.='SiO2']">
> 
> to return the fragment
> 
> <vendor name="james">
>  <product id="1234">
>   <material>SiO2</material>
>  </product>
> </vendor>
> 

Brute force solution.... how can this be improved?

......

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                 version="1.0">
<xsl:output method="xml"/>

<xsl:template match="//material[.='SiO2']" >
  <xsl:call-template name="print-fragment" />  
</xsl:template>

<xsl:template match="*" >
  <xsl:apply-templates/>
</xsl:template>

<xsl:template match="text()" />

<xsl:template name="print-fragment" >
  <!-- This template prints out the XML fragment
       from the starting element to the stop element.
       By default, the starting element is the first
       element in the document "/*[1]", and the stopping
       element is the current element "." 
   -->
  <xsl:param    name="start"    select="/*[1]" />
  <xsl:param    name="stop"     select="." />
  <xsl:for-each select="$stop/ancestor-or-self::*" >
    <xsl:variable name="parent-id" select="generate-id(..)" />
    <xsl:if test="generate-id(..)=generate-id($start)">
        <xsl:element name="{name(..)}">
        <xsl:for-each select="../@*" >
          <xsl:attribute name="{name()}">
            <xsl:value-of select="." />
          </xsl:attribute>
        </xsl:for-each>
        <xsl:choose>
          <xsl:when test="generate-id(.)=generate-id($stop)">
             <xsl:element name="{name()}">
               <xsl:for-each select="@*" >
                 <xsl:attribute name="{name()}">
                   <xsl:value-of select="." />
                 </xsl:attribute>
               </xsl:for-each>
               <xsl:value-of select="." />
             </xsl:element>
          </xsl:when>
          <xsl:otherwise>
            <xsl:call-template name="print-fragment" >
              <xsl:with-param name="stop"    select="$stop" />
              <xsl:with-param name="start"   select="."     />
            </xsl:call-template>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:element>
    </xsl:if>
  </xsl:for-each>
</xsl:template>

</xsl:stylesheet>





 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread