RE: Fwd: [xsl] complex XPATH test

Subject: RE: Fwd: [xsl] complex XPATH test
From: Nate Austin <naustin@xxxxxxxxxx>
Date: Tue, 17 Jul 2001 13:58:14 -0500
Adam and Wendell,

Here's the solution I came up with, which raised a question or two itself.

<xsl:template match="br">
  <xsl:variable name="containing-block" select="ancestor::p[1]"/>
  <!-- use '1' for the predicate since ancestor axis returns reverse
document order -->
  <xsl:variable name="curr" select="current()"/>
  <xsl:variable name="currPos">
    <xsl:for-each select="$containing-block/descendant::node()">
      <xsl:if test="count(.|$curr) = count(.)">
        <xsl:value-of select="position()"/>
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>
  <!-- $containing-block/descendant::node()[.=current()]/position() (doesn't
work)-->
  <xsl:if test="$containing-block/descendant::node()[position() &gt;
$currPos]"> 
    <br/>
  </xsl:if>
</xsl:template>

For starters, there has to be a better way of returning the position of a
node within a node set than what I used here (the for-each block).  Anyone
have any ideas?  I tried 
<xsl:variable name="currPos"
select="$containing-block/descendant::node()[.=current()]/position()"/>
knowing it wouldn't work (from previous posts to the list, etc.) and I
wasn't disappointed.  So the question I have is:  How do you return the
position of a node in a node set given the node and the node set, so that
the position can be used in a comparison or a variable?
Second, why is it that ".=$curr" tests the value of each against each other,
rather than a 'node id' or something?  Wouldn't it make sense for that to
actually check that the nodes are equivalent since if I wanted to check
their string values I could do "string(.)=string($curr)" but I can't do the
reverse. (ie. "node(.)=node($curr)" or something).  I'm I overlooking
something here?  This is getting long, maybe it's time for a new thread. <g>

Back to Adam's original problem...  this will output the <br/> if there are
any nodes further down the tree from the block element than the <br/> tag
is, so it may or may not give you the results you want.  For instance:
<p>this is a little bit of text<br /><br /></p>

would return

<p>this is a little bit of text<br /></p>

also,
<p>this is a little bit of text<br />
</p>

would return
<p>this is a little bit of text<br />
</p>

if you didn't strip the whitespace ahead of time.

I'm with Wendell.  I'd still like to see a slick solution.

-Nate
naustin@xxxxxxxxxx

> Date: Mon, 16 Jul 2001 19:03:24 -0400
> From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
> Subject: Re: [xsl] complex XPATH test
> 
> Adam,
> 
> <xsl:template match="br">
>    <!-- 1st, retrieve the block ancestor you're worried about -->
>    <xsl:variable name="containing-block" 
> select="(ancestor::p|ancestor::li|ancestor::blockquote)[last()]"/>
>    <!-- (you'll have to extend that list to include all the possible 
> blocks) -->
>    <!-- now, figure out what text nodes are actually 
> following inside the 
> block -->
>    <xsl:variable name="text-following">
>    <xsl:for-each 
> select="$containing-block//text()[.=current()/following::text()">
>       <xsl:value-of select="."/>
>    </xsl:for-each>
>    <!-- now, include the br if there's anything there besides 
> white space -->
>    <xsl:if test="normalize-space($text-following)">
>       <xsl:copy-of/>
>    </xsl:if>
> </xsl:template>
> 
> (untested)
> 
> It's slow and painful, but then those <br> elements are painful too.
> 
> What do you think? I'd like to see a slick solution, too....
> 
> Cheers,
> Wendell
> 
> At 06:11 PM 7/16/01, you wrote:
> >Hey guys,
> >
> >I'm working on an transform that will take well formed HTML 
> and convert it
> >into a different prose schema (NITF).
> >
> >I'm trying to do some intelligent filtering of valid, but 
> meaningless HTML
> >markup (the DHTML Edit control will occasionally give me 
> stuff I'm not too
> >happy aobut).
> >
> >If I have a <br> tag inside a block element, I only want to 
> deal with it if
> >its not the last br tag. An example
> >
> >I care about the br in :
> ><p> this is some text<br />
> >here is some more</p>
> >
> >but not in:
> ><p>this is a little bit of text<br /></p>
> >
> >My original test was
> ><xsl:template match="br">
> >         <xsl:if test="count(following-sibling::node()) &gt; 0">
> >                 <br/>
> >         </xsl:if>
> ></xsl:template>
> >
> >but I ran into a problem with the following:
> >
> ><p><strong>this is some bolded text<br/></strong>Some more text</p>
> >
> >since the br was getting ignored.
> >
> >What I want to do is test that the context node is not the 
> last child of the
> >context node's ancestor block node. Its also not the case 
> that immediate
> >parent of that block node will be <body> since <li> is a 
> block node and is a
> >child of <ol> or <ul>.
> >
> >Any thougths?
> >
> >Adam van den Hoven
> >Internet Software Developer
> >Blue Zone
> >tel. 604 685 4310 ext. 260
> >fax 604 685 4391
> >
> > > Blue Zone makes you interactive. http://www.bluezone.net/
> > >
> > >
> > >
> Date: Mon, 16 Jul 2001 19:11:45 -0400
> From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
> Subject: Fwd: Re: [xsl] complex XPATH test
> 
> Oops, I realized there's one bug... the equality test
> 
> $containing-block//text()[.=current()/following::text()]
> 
> (I also note typo in my code, missing ']')
> 
> isn't going to do the trick. You're going to need some kind of 
> intersection. Like
> 
> $containing-block//text()[count(.|current()/following::text())
> =count(current()/following::text())]
> 
> which will really be horrible and slow, even if you put 
> current()/following::text(), and its count, into a variable....
> 
> Anyone else? Heh,
> Wendell
> 
> 
> >Date: Mon, 16 Jul 2001 19:03:24 -0400
> >To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> >From: Wendell Piez <wapiez@xxxxxxxxxxxxxxxx>
> >Subject: Re: [xsl] complex XPATH test
> >
> >Adam,
> >
> ><xsl:template match="br">
> >   <!-- 1st, retrieve the block ancestor you're worried about -->
> >   <xsl:variable name="containing-block" 
> > select="(ancestor::p|ancestor::li|ancestor::blockquote)[last()]"/>
> >   <!-- (you'll have to extend that list to include all the possible 
> > blocks) -->
> >   <!-- now, figure out what text nodes are actually 
> following inside the 
> > block -->
> >   <xsl:variable name="text-following">
> >   <xsl:for-each 
> > select="$containing-block//text()[.=current()/following::text()">
> >      <xsl:value-of select="."/>
> >   </xsl:for-each>
> >   <!-- now, include the br if there's anything there 
> besides white space -->
> >   <xsl:if test="normalize-space($text-following)">
> >      <xsl:copy-of/>
> >   </xsl:if>
> ></xsl:template>
> >
> >(untested)
> >
> >It's slow and painful, but then those <br> elements are painful too.
> >
> >What do you think? I'd like to see a slick solution, too....

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


Current Thread