This is the mail archive of the
xsl-list@mulberrytech.com
mailing list .
RE: Fwd: complex XPATH test
- To: "'xsl-list at lists dot mulberrytech dot com'" <xsl-list at lists dot mulberrytech dot com>
- Subject: RE: Fwd: [xsl] complex XPATH test
- From: Nate Austin <naustin at idsgrp dot com>
- Date: Tue, 17 Jul 2001 13:58:14 -0500
- Reply-To: xsl-list at lists dot mulberrytech dot com
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() >
$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@idsgrp.com
> Date: Mon, 16 Jul 2001 19:03:24 -0400
> From: Wendell Piez <wapiez@mulberrytech.com>
> 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()) > 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@mulberrytech.com>
> 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@lists.mulberrytech.com
> >From: Wendell Piez <wapiez@mulberrytech.com>
> >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