Re: [xsl] Searching for an attribute across different elements with ancestoral elements returned

Subject: Re: [xsl] Searching for an attribute across different elements with ancestoral elements returned
From: "Rob Lugt" <roblugt@xxxxxxxxx>
Date: Fri, 20 Jul 2001 13:25:07 +0100
David Glover wrote


> I have a Products XML file that is of the following simple form :
> <BRAND>
> <LINE ID="1">
> <ITEM OFFER="BUYXGET1FREE"/>
> <ITEM/>
> <ITEM/>
> <ITEM/>
> </LINE>
> <LINE ID="2">
> <ITEM/>
> <ITEM/>
> <ITEM/>
> <ITEM/>
> </LINE>
> <LINE ID="3" OFFER="BUYXGET1FREE">
> <ITEM/>
> <ITEM/>
> <ITEM/>
> <ITEM/>
> </LINE>
> </BRAND>
>
> At any level an @OFFER attribute is used to indicate a special deal
> applicable to the whole level and its children.
>
> I wish to return all brands/lines/items that have this @OFFER attribute.
> If it is an ITEM I wish to return its parent LINE and grandparent BRAND as
> well.  If it is a LINE, I wish to return its child ITEMs and parent BRAND
as
> well.  If it is BRAND I wish it to return its child LINEs and its
> grandchildren ITEMs. I DO NOT WANT any siblings of the matched element.
>
> I've tried the following 2 patterns :
>
> //BRAND/LINE[@OFFER] | //BRAND/LINE[ITEM[@OFFER]] |
> //BRAND/LINE[ITEM[@OFFER]]
> The problem with this was, that siblings were returned.
>
> //*[@OFFER]
> The problem with this was it failed to return parents of the matched
items.
>
> Given the above example XML and the correct XPATH expression I'm looking
for
> the following returned XML :
> <BRAND>
> <LINE ID="1">
> <ITEM OFFER="BUYXGET1FREE"/>
> </LINE>
> <LINE ID="3" OFFER="BUYXGET1FREE">
> <ITEM/>
> <ITEM/>
> <ITEM/>
> <ITEM/>
> </LINE>
> </BRAND>

Conceptually this is not difficult, you just need to think clearly what is
required.

I believe you have two simple cases: -
1)  If there are children with an OFFER attribute, then copy the current
element and recurse down the tree
2)  If there is an ancestor (or self) with an OFFER attribute then copy the
entire branch below that element.

This is simply achieved with the following template:-

<xsl:template match="node()">
 <xsl:choose>
  <!-- if there are children with an OFFER attribute, copy node and recurse
down the tree -->
  <xsl:when test="descendant::node()/@OFFER">
   <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates/>
   </xsl:copy>
  </xsl:when>
  <!-- if there is an ancestor-or-self with an OFFER attribute, copy entire
branch -->
  <xsl:when test="ancestor-or-self::node()/@OFFER">
   <xsl:copy-of select="."/>
  </xsl:when>
 </xsl:choose>
</xsl:template>

Hope this helps
~Rob



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


Current Thread