Re: [xsl] ancestor

Subject: Re: [xsl] ancestor
From: "M. David Peterson" <m.david@xxxxxxxxxx>
Date: Mon, 18 Oct 2004 09:33:04 -0700
You know there are a few people on this list whom, no matter what my schedule is like, I always find the time to read there posts because they always contain that extra bit of information or a "clear as a bell" explanation that I had never seen or thought of before. Jeni is one of those people. It never ceases to amaze me when how she can take a small statement and piece of data from a question (that to me is completely meaningless) and piece together exactly what it is they are trying to do, providing a complete explanation, with several examples to boot.

I've been meaning to go and pick up your latest book Jeni, and I think today is the day I am going to do that... I can only imagine how much more depth and understanding is contained within its pages.

Thanks for all these years of free education!

Cheers,

<M:D/>

Jeni Tennison wrote:
Hi Peiyun,


I'm trying to get all inlineequation elements that are not in the table
element. The following is not working. I don't know why. I always get all
the inlineequation elements.

select="//inlineequation[not (ancestor::* = 'table')]"


This selects all <inlineequation> elements that do not have an
ancestor element whose *value* is 'table'. To select all
<inlineequation> elements that do not have a <table> element as an
ancestor, you can use:

select="//inlineequation[not(ancestor::table)]

The path "ancestor::table" selects the <table> ancestor element, if
there is one.


I know this can be very expensive even if it works. What cab be a
better way to do it?


The thing that's expensive here is the use of the descendant-or-self::
axis (implicit in the "//" at the beginning of the path), which means
that the processor has to search the entire document for the
<inlineequation> elements. Anything that you can do to narrow down the
search for the processor will help. It might be that you can search
only within the element that you're currently on (use
".//inlineequation") or that you can use the natural recursion of the
templates to get these elements.

If you have lots of tables, for example, then rather than doing:

<xsl:apply-templates select="//inlinequation[not(ancestor::table)]"/>

it might be more efficient to use templates to filter down the
subtrees that get searched. Use modes -- in 'inlineequation' mode,
you're only interested in <inlineequation> elements. Apply templates
to the top of the tree:

<xsl:apply-templates select="/" mode="inlineequation" />

and then have a template for <inlineequation> elements:

<xsl:template match="inlineequation" mode="inlineequation">
  ... do something ...
</xsl:template>

Let the built-in templates do their work (recurse down the tree), but
have templates to stop processing whenever you come to an element that
can't contain an <inlineequation> element that you're interested in,
such as a table:

<xsl:template match="table" mode="inlineequation" />

This assumes that you really want to collect together all the
<inlineequation> elements -- that you're creating a "List of
Equations" or something -- if that's not what you're doing, then
there's probably a more efficient approach, but it would require
looking at more of your stylesheet to know what's suitable.

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/

Current Thread