Re: [xsl] ancestor

Subject: Re: [xsl] ancestor
From: Jeni Tennison <jeni@xxxxxxxxxxxxxxxx>
Date: Mon, 18 Oct 2004 17:16:18 +0100
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