[xsl] Removing entire branches from a node-set

Subject: [xsl] Removing entire branches from a node-set
From: ERDI Gergo <cactus@xxxxxxxxxxxxxxxx>
Date: Mon, 10 Jan 2005 12:24:16 +0100 (CET)
Hi,

I'd like to create a node-set by applying a specific criterion to whole branches. Formally:

test(): a predicate test on nodes
tree(R, C1, C2, ...): a tree with root R and immediate children C1, C2, ...

rfilter(T) = NULL, if not test(T.root)
             tree (T.root, rfilter (T.c1), rfilter (T.c2), ...), if test (T.root)

The problem is, if I do something like /descendant::node()[test()], the children of nodes that do not meet test() are still considered.

Specifically, what I want is having an input like this:

<root>
  <node>This node should always be included in the node-set</node>
  <node lang="en">This node should only be included in the <b>English</b> node-set</node>
  <node lang="de">This node should only be included in the <b>German</b> node-set</node>
</root>

test() = (@lang='en' or not(@lang))

Of course, the problem comes from /root/node[3]/b: it passes test(), but since it has an ancestor (/root/node[3]) that doesn't, it shouldn't be included in the node-set.

I tried

/descendant::node()[(ancestor-or-self::node()/@lang='en'
                     or not (ancestor-or-self::node()/@lang))
		    and not(ancestor-or-self::node()/@lang!='en')]

but this just results in everything getting included in the node-set several times (as a grandchild of an included node, then as a child, then as itself), plus, since it matches /root, it first includes the whole tree unfiltered :(

Any ideas how I could solve this?

--
   .--= ULLA! =---------------------.   `We are not here to give users what
   \     http://cactus.rulez.org     \   they want'  -- RMS, at GUADEC 2001
    `---= cactus@xxxxxxxxxxxxxxxx =---'
F U CN RD THS U CNT SPL WRTH A DM!

Current Thread