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::*[(_at_)att][last()]
Michael Kay
Software AG
home: Michael(_dot_)H(_dot_)Kay(_at_)ntlworld(_dot_)com
work: Michael(_dot_)Kay(_at_)softwareag(_dot_)com
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[(_at_)id=2] and page[(_at_)id=3] to inherit @style from
page[(_at_)id=1], page[(_at_)id=4] to inherit @style from page[(_at_)id=0],
page[(_at_)id=6] to inherit from page[(_at_)id=5], and page[(_at_)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[(_at_)id=3] has now inherited @style from
the outermost ancestor that defines a style attribute
(page[(_at_)id=0), which is not what I want - I want it to inherit
from page[(_at_)id=1](_dot_)
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