Re: [xsl] Deleting following sibling element

Subject: Re: [xsl] Deleting following sibling element
From: owner-xsl-list@xxxxxxxxxxxxxxxxxxxxxx (by way of B. Tommie Usdin)
Date: Thu, 18 Jan 2001 18:27:02 -0500
From: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
X-Mailer: The Bat! (v1.49) Business
Reply-To: Jeni Tennison <mail@xxxxxxxxxxxxxxxx>
Organization: Jeni Tennison Consulting Ltd
X-Priority: 3 (Normal)
Message-ID: <10988881044.20010117094336@xxxxxxxxxxxxxxxx>
To: Edierley Messias <edierley@xxxxxxxxxxx>
CC: xsl-list <xsl-list@xxxxxxxxxxxxxxxxxxxxxx>
Subject: Re: [xsl] Deleting following sibling element
In-reply-To: <a0500190bb68a9e7f363e@[209\.179\.157\.251]>
References: <a0500190bb68a9e7f363e@[209.179.157.251]>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi Eiderley,

 Does anybody knows how can I delete an element that is the next
 following-sibling of the context node?

Rather than thinking of it in terms of 'deleting' an element, think in terms of 'not including' an element. Remember in XSLT you're building a completely new node set - if you don't want something to appear in it, don't put it there :)

 For example:
 [XML]
 <a href="anything">link</a><br/>

 [XSL]
 <xsl:template match="//a[name(following-sibling::*[1])='br']">
     ????
 </xsl:template>

 [The XML Output should be]
 <a href="anything">link</a>
 ------------------------------------
 I'm using the template to copy all nodes and attributes, so
 the <br/> will also be copied.

 I can match the template using the <br/> element because I already wrote
 another templates thats match the <br/>

There are two ways of not including the output for something in your result - have a template that does nothing when you apply templates to it, or don't apply templates to it in the first place.

Taking the first one first: you need to match the thing that you don't
want copied and do nothing with it.  In your case, you need to match
any 'br' who's immediately preceding sibling is an 'a' element:

br[preceding-sibling::*[1][self::a]]

[Note - it's better to use self::a rather than comparing the name()s
of the nodes because it deals nicely with namespaces.] A template for
this would be:

<xsl:template match="br[preceding-sibling::*[1][self::a]]" />

If you have other templates that match br elements, either with
predicates like this one or that match brs in context, specifying
parents and so on, then you have to assign a higher priority to this
template:

<xsl:template match="br[preceding-sibling::*[1][self::a]]"
              priority="2" />

You could also cheat and just put it lower down in the stylesheet than
the other templates.

Using the other method, not applying templates to it in the first
place, is somewhat better in that it stops the processor having to go
through the whole 'finding the relevant template' process, which can
be time-consuming. How you prevent the template being applied depends
on how you're applying the templates. If you're doing it in the normal
way (parent to children), then whenever you have a possible parent of
one of these br elements, you need to filter them out in the
xsl:apply-templates:

   <xsl:apply-templates
     select="*[not(self::br and preceding-sibling::*[1][self::a])]" />

Of course if you're having to repeat this all over the place, it's
just a lot easier to have an empty template act as the filter.

I hope that helps,

Jeni

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

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


Current Thread