470,848 Members | 1,197 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,848 developers. It's quick & easy.

templates and xpath expr with predicate and first and last functions

HI,

I have some data like:
<x>
<y Position='Top'/>
<y/>
<x/>

and a template like:
<xsl:template match="/x/y[@Position='Top']">
<li>
<xsl:if test="position()=last()">
<xsl:attribute name="class">last</xsl:attribute>
</xsl:if>
</li>
</xsl:template>

I want to catch the last y with a position of Top
unfortunately position and last work on a list of y elements, not a list of
y[@Position='Top'] elements.

In fact it's even worse than that.
If my data was
<x>
<y Position='Top'/>
<y/>
<z/>
<x/>

last() would be 3, not 2

Does any one have a work around for this bug?

Thanks
Martin
Mar 7 '06 #1
5 1134


Martin wrote:
I have some data like:
<x>
<y Position='Top'/>
<y/>
<x/>
Where is the closing </x> then? It is not clear whether that first x
element has two y child elements as well as an x child element.
and a template like:
<xsl:template match="/x/y[@Position='Top']">
<li>
<xsl:if test="position()=last()">
<xsl:attribute name="class">last</xsl:attribute>
</xsl:if>
</li>
</xsl:template>

I want to catch the last y with a position of Top
unfortunately position and last work on a list of y elements, not a list of
y[@Position='Top'] elements.


The template does not change the type and size of the current node list.
You simply need to use xsl:apply-templates to filter out nodes first e.g.
<xsl:apply-templates select="y[@Position = 'Top']" />

--

Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/
Mar 7 '06 #2
Oops sorry, the data should read (1 x root, 2 y children)
<x>
<y Position='Top'/>
<y/>
</x>

The rest of the problem description remains.
Thanks
Martin

"Martin Honnen" <ma*******@yahoo.de> wrote in message
news:eG**************@TK2MSFTNGP09.phx.gbl...

Martin wrote:
I have some data like:
<x>
<y Position='Top'/>
<y/>
<x/>


Where is the closing </x> then? It is not clear whether that first x
element has two y child elements as well as an x child element.
and a template like:
<xsl:template match="/x/y[@Position='Top']">
<li>
<xsl:if test="position()=last()">
<xsl:attribute name="class">last</xsl:attribute>
</xsl:if>
</li>
</xsl:template>

I want to catch the last y with a position of Top
unfortunately position and last work on a list of y elements, not a list
of y[@Position='Top'] elements.


The template does not change the type and size of the current node list.
You simply need to use xsl:apply-templates to filter out nodes first e.g.
<xsl:apply-templates select="y[@Position = 'Top']" />

--

Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/

Mar 7 '06 #3
Having read some more, I think it's correct xslt behaviour, but it's still
not what I want.

I need to control the context size to be what I require it to be, maybe with
an apply-templates select clause.

Here is my new xslt which seems to fit the bill:
<xsl:template match="/x/y[1]">
<xsl:apply-templates select="/x/y[@Position='Top']" mode="test"/>
</xsl:template>

<xsl:template match="y" mode="test">
p=<xsl:value-of select="position()"/>
l=<xsl:value-of select="last()"/>
x
</xsl:template>

Martin

"Martin" <x@y.z> wrote in message
news:OM**************@TK2MSFTNGP11.phx.gbl...
Oops sorry, the data should read (1 x root, 2 y children)
<x>
<y Position='Top'/>
<y/>
</x>


The rest of the problem description remains.
Thanks
Martin

"Martin Honnen" <ma*******@yahoo.de> wrote in message
news:eG**************@TK2MSFTNGP09.phx.gbl...


Martin wrote:
I have some data like:
<x>
<y Position='Top'/>
<y/>
<x/>


Where is the closing </x> then? It is not clear whether that first x
element has two y child elements as well as an x child element.
and a template like:
<xsl:template match="/x/y[@Position='Top']">
<li>
<xsl:if test="position()=last()">
<xsl:attribute name="class">last</xsl:attribute>
</xsl:if>
</li>
</xsl:template>

I want to catch the last y with a position of Top
unfortunately position and last work on a list of y elements, not a list
of y[@Position='Top'] elements.


The template does not change the type and size of the current node list.
You simply need to use xsl:apply-templates to filter out nodes first e.g.
<xsl:apply-templates select="y[@Position = 'Top']" />

--

Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/


Mar 7 '06 #4


Martin wrote:
Oops sorry, the data should read (1 x root, 2 y children) The rest of the problem description remains.


Well I suggested a change in my earlier post


The template does not change the type and size of the current node list.
You simply need to use xsl:apply-templates to filter out nodes first e.g.
<xsl:apply-templates select="y[@Position = 'Top']" />


--

Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/
Mar 7 '06 #5
Thanks Martin.

Very tired today.

Martin
"Martin Honnen" <ma*******@yahoo.de> wrote in message
news:ex**************@TK2MSFTNGP15.phx.gbl...


Martin wrote:
Oops sorry, the data should read (1 x root, 2 y children)

The rest of the problem description remains.


Well I suggested a change in my earlier post


The template does not change the type and size of the current node list.
You simply need to use xsl:apply-templates to filter out nodes first e.g.
<xsl:apply-templates select="y[@Position = 'Top']" />


--

Martin Honnen --- MVP XML
http://JavaScript.FAQTs.com/

Mar 7 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.