[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: Selecting all nodes between pairs of <br> tags

Subject: Re: Selecting all nodes between pairs of <br> tags
From: Duncan Anker <danker@xxxxxxxxxxxxx>
Date: Tue, 20 Jun 2006 13:55:37 +1000
local name preceding
Hi Mukul,
<xsl:template name="stat">
<xsl:param name="nodeset" />
<xsl:if test="not((local-name($nodeset[1]) = 'br') and
(local-name($nodeset[2]) = 'br'))">
  <!-- do something with the node; i.e $nodeset[1] -->
  <xsl:call-template name="stat">
    <xsl:with-param name="nodeset" select="$nodeset[position &gt; 1]" />
  </xsl:call-template>
</xsl:if>
</xsl:template>

I could not give this code earlier because your source XML data was
not enough for me to formulate this solution.
Thank you very much for that. It looks a bit more elegant than what I had started coming up with - I think because most similar solutions involve xsl:for-each, I stopped thinking about recursion. Now I'm having flashbacks of my brief experience with Prolog many years ago :)

I think I can probably get something working shortly, although I am still seeing the issue where the nodeset is being processed after the template call. What I mean by that is <br><br><b>A</b>B<br><br> will output <!-- result from template call --><br><b>A</b>B<br> and I would like the template to continue from after the 2nd <br> pair, not from the point it was at when the call was made.

Is there a convenient way to skip the processed nodes, or is the solution another template which matches each item in the list to suppress it - this seems like it would suffer from the same problem though.

Regards,
Duncan

On 6/16/06, Duncan Anker <danker@xxxxxxxxxxxxx> wrote:
Hi List,

I am still having trouble grasping some of the more subtle points of
XPath. Consider the following HTML:

...
<br><br>
<b>A</b>B<br>
...
<br><br>
C
<br><br>
<div>
...

Following the advice of Mukul Gandhi given me a few weeks ago, I use
match="br[local-name(preceding-sibling::node()[1]) = 'br'][1]" (I am
using xsltproc with the --html option, which I suspect is normalizing
the spaces so this is slightly modified from the sample given):

I then select the nodes following with
select="following-sibling::node()[normalize-space != '']" - this is then
passed into a template which which outputs the A and B elements (I
handle these explicitly, which may be cheating, because I can't figure
out how to stop at <br> and I know the format of the data).

This is all well and good, except that my output comes out like this:

<ul>
<li><label>A</label>B</li>
...
<li><label>C</label></li>
<b>A</b><br> ...

Currently, the selection of following siblings seems to select up to the
3rd <br> pair. This in itself is slightly odd, since I would have
thought it would select everything following at the same level, although
it appears to stop at the div tag, so perhaps the match ends there for
some pre-determined reason. In any case, I would like it to stop at the
second <br> tag pair - it seems like using a following-sibling rule
inside a predicate won't work easily since elements after the 2nd <br>
pair are followed by the 3rd <br> pair, so would still be included.
There must be some way to specify all following siblings up to <br><br>
and excluding anything after the <br><br> but the thought of what that
expression might look like is making my eyes glaze.

The other problem is the labels being output afterwards - it would seem
that this is matching where the previous template leaves off. I don't
understand why it outputs only the label and not the following data. Any
suggestions?

The relevant template:

<xsl:template match="br[local-name(preceding-sibling::node()[1]) = 'br'][1]">

<ul>

<xsl:call-template name="stat">

<xsl:with-param name="nodeset"

select="following-sibling::node()[normalize-space() != '']" />

</xsl:call-template>

</ul>

</xsl:template>

<xsl:template name="stat">

<xsl:param name="nodeset" />

<xsl:for-each select="$nodeset[position() mod 2 = 1]">

<li>

<label><xsl:value-of select="." /></label>

<xsl:value-of select="normalize-space(following-sibling::text())" />

</li>

</xsl:for-each>

</xsl:template>


Thanks in advance. Duncan

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2011 All Rights Reserved.