xsl-list
[Top] [All Lists]

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

2006-06-18 21:49:03
Hi Duncan,
 Sorry for replying a bit late to your question.

I think your "stat" template would look something like this:

<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.

Also, you may have to fine tune the whole code to suit your requirement.

Regards,
Mukul


On 6/16/06, Duncan Anker <danker(_at_)server101(_dot_)com> 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

--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--