RE: [xsl] XPath: better way to check for text nodes that aren't descendents of x or y nodes?

Subject: RE: [xsl] XPath: better way to check for text nodes that aren't descendents of x or y nodes?
From: "Lars Huttar" <lars_huttar@xxxxxxx>
Date: Wed, 14 May 2003 15:03:40 -0500
Tom Passim wrote:
> You could use
> 
> test='not(.//*[local-name() != "vernac" and local-name() !=
> "gloss"]/text()[1]
> 		| text())'

Hmm... I don't think this would give the correct result in all cases,
e.g. if we have
  ./llcd:vernac/llcd:stretch/text()
this should be legal, but it would show up as illegal by your test.

> 
> or
> 
> test='count(.//*[local-name() != "vernac" and local-name() !=
> "gloss"]/text()[1]
> 		| text()) > 0'
> 
> These might be more efficient because you do not bother to examine
> elements that will not cause a false result, and of the ones that are
> examined, you only have to look at one text node.

That's the kind of solution I was hoping for...

> Whatever expression you use, remember to use 
> 
> <xsl:strip-space elements='*'/>
> 
> Otherwise you will be counting whitespace-only nodes between elements,
> which you most likely do not intend.

Thanks!  That may save me some grief.


Dmitre Novatchev wrote:
> Or quite more simple:
> 
>   count(.//text()) != count(.//*[self::llcd:vernac or
> self::llcd:gloss]//text())

Thanks... I had not thought to use *[self::llcd:vernac or
  self::llcd:gloss] in the middle.

Do you have any thoughts about the efficiency of a count() solution
vs. a count()-less solution like the following one?  (using "or" instead
of "|" as you suggest)

> > My current test is
> >  test=".//text()[not(ancestor::llcd:vernac | ancestor::llcd:gloss)]"
> 
> In the general case this is not correct, because it will 
> permit "illegal"
> text-nodes, which have an llcd:vernac or llcd:gloss ancestor, 
> which is not a
> descendent of the current node (but its ancestor).

In my first email I noted that
> (By the way, if it helps, the llcd:vernac or llcd:gloss will be descendants
> of . too, not ancestors.)
What I meant is that this constraint can be assumed
to be true already.  So there are no llcd:vernac or llcd:gloss ancestors
of the current node.

> Apart from this observation, a non-clever XSLT processor will 
> build the
> union in the predicate and this is quite expensive operation. 
> I think it
> would be more efficient to re-write the expression as:
> 
> .//text()[not(ancestor::llcd:vernac or ancestor::llcd:gloss)]

Thanks, that's helpful.
Sometimes I forget that | is really union and not just "or"!

Lars


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


Current Thread