This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Deleting following sibling element


From: Jeni Tennison <mail@jenitennison.com>
X-Mailer: The Bat! (v1.49) Business
Reply-To: Jeni Tennison <mail@jenitennison.com>
Organization: Jeni Tennison Consulting Ltd
X-Priority: 3 (Normal)
Message-ID: <10988881044.20010117094336@jenitennison.com>
To: Edierley Messias <edierley@dcc.ufmg.br>
CC: xsl-list <xsl-list@lists.mulberrytech.com>
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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]