RE: [xsl] Inheriting an attribute from first ancestor that defines it

Subject: RE: [xsl] Inheriting an attribute from first ancestor that defines it
From: "Michael Kay" <michael.h.kay@xxxxxxxxxxxx>
Date: Fri, 25 Oct 2002 19:14:17 +0100
> I'd like to have child elements inherit an attribute from the 
> first ancestor in their ancestry that defines it.

(ancestor::*/@att)[last()]

Note the brackets, because you want the last of all the attributes, not
the last attribute of a particular ancestor. Note also that it's the
last (in document order) not the first.

The above selects the attribute, if you want to select the element, use

ancestor::*[@att][last()]

Michael Kay
Software AG
home: Michael.H.Kay@xxxxxxxxxxxx
work: Michael.Kay@xxxxxxxxxxxxxx 

> 
> Specifically, is there a more general way (than specifying 
> test="../@attr",
> test="../../@attr") to select the first ancestor travelling 
> back up the tree that defines a specific attribute?
> 
> This is my example xml doc:
> 
> <?xml version="1.0" encoding="utf-8"?>
> <doc style="doc">
>   <page id="0" style="default">
>     <page id="1" style="page1">
>       <page id="2">
>         <page id="3"/>
>       </page>
>     </page>
>     <page id="4">
>       <page id="5" style="page5">
>         <page id="6"/>
>         <page id="7" style="page7"/>
>       </page>
>     </page>
>   </page>
> </doc>
> 
> Please note that the ids are just for reference here - I 
> don't want to refer to them in the stylesheet.
> 
> I'd like page[@id=2] and page[@id=3] to inherit @style from 
> page[@id=1], page[@id=4] to inherit @style from page[@id=0], 
> page[@id=6] to inherit from page[@id=5], and page[@id=7] to 
> use its own @style attribute.
> 
> In other words, I'd like the following output:
> 
> <?xml version="1.0" encoding="utf-8"?><doc style="doc">
>   <page id="0" style="default">
>     <page id="1" style="page1">
>       <page id="2" style="page1">
>         <page id="3" style="page1"></page>
>       </page>
>     </page>
>     <page id="4" style="default">
>       <page id="5" style="page5">
>         <page id="6" style="page5"></page>
>         <page id="7" style="page7"></page>
>       </page>
>     </page>
>   </page>
> </doc>
> 
> Now, this stylesheet works for my particular example (with 
> the above level of nesting):
> 
> <?xml version="1.0" encoding="utf-8"?>
> <xsl:stylesheet version = '1.0' 
> xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
> 
> <xsl:output method="xml" encoding="utf-8"/>
> 
> <xsl:template match="/">
>   <xsl:apply-templates/>
> </xsl:template>
> 
> <xsl:template match="//page">
> 
>   <page>
>     <xsl:copy-of select="@*"/>
> 
>     <xsl:attribute name="style">
>       <xsl:choose>
>         <xsl:when test="@style">
>           <xsl:value-of select="@style"/>
>         </xsl:when>
>         <!-- parent's attribute -->
>         <xsl:when test="../@style">
>           <xsl:value-of select="../@style"/>
>         </xsl:when>
>         <!-- grandparent's attribute -->
>         <xsl:when test="../../@style">
>           <xsl:value-of select="../../@style"/>
>         </xsl:when>
>         <!-- ancestor's attribute -->
>         <xsl:otherwise>
>           <xsl:value-of select="ancestor::*/@style"/>
>         </xsl:otherwise>
>       </xsl:choose>
>     </xsl:attribute>
> 
>     <xsl:apply-templates/>
> 
>   </page>
> 
> </xsl:template>
> 
> 
> <!-- Identity transformation -->
> <xsl:template match="@*|*">
>  <xsl:copy>
>   <xsl:apply-templates select="@*|node()"/>
>  </xsl:copy>
> </xsl:template>
> 
> </xsl:stylesheet>
> 
> But if I add more levels of nesting, I have to define further 
> rules to match ../../../, etc.
> 
> My problem with "ancestor::*/@style" is that it selects the 
> outermost ancestor's attribute.
> 
> For example, if I remove the selector for the grandparent's 
> attribute, I get the following:
> 
> <?xml version="1.0" encoding="utf-8"?><doc>
>   <page id="0" style="default">
>     <page id="1" style="page1">
>       <page id="2" style="page1">
>         <page id="3" style="default"></page>
>       </page>
>     </page>
>     <page id="4" style="default">
>       <page id="5" style="page5">
>         <page id="6" style="page5"></page>
>         <page id="7" style="page7"></page>
>       </page>
>     </page>
>   </page>
> </doc>
> 
> You'll note that page[@id=3] has now inherited @style from 
> the outermost ancestor that defines a style attribute 
> (page[@id=0), which is not what I want - I want it to inherit 
> from page[@id=1].
> 
> Thanks in advance for any help you can offer.
> 
> Regards,
> 
> Sean O'Halpin
> 
>  XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
> 
> 


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


Current Thread