Altova Mailing List Archives>Archive Index >microsoft.public.xsl Archive Home >Recent entries >Thread Prev - Re: Previous value in a for-each [Thread Next] Re: Previous value in a for-eachTo: NULL Date: 11/3/2004 9:13:00 PM Hi Jason, No, you've got it horribly wrong - partly my fault for not explaining something which i take as read when talking about XPath... When I said... x = x + 1 is an impossibility - it is because the '=' is a comparator (not an assignment). So the '=' is a test for equality... an as x can never equal x+1 that is why it is impossible. There is absolutely no notion of assignment in XPath 1.0 - you cannot create variables; you cannot assign anything. If you always remember that XPath (at least XPath 1.0) is a "selection language" you won't get led astray - as selection language can only select things... as opposed to a query language that can assign things and create things. The position() function is a function like any other function in XPath - it only returns something. And like any other function in XPath, and just about any other language, it cannot be 'assigned'. The position() function returns the position of the 'current' item within the node-set currently being processed. This 'current' part is the difference between the two ways position() can be used... For example, if you do (wherever)... <xsl:value-of select="position()"/> you are asking for the position of the current context node within the the currently processed node-set - typically a node-set that was selected by the @select attribute of <xsl:apply-templates> or <xsl:for-each>. Another example would be to use the position() within a predicate [] condition, e.g. <xsl:for-each select="item[position() = 3]"> in this case the position() function is returning the position within the node-set selected to the left of the predicate [] part. (NB. Although it is unusual, and unhealthy, to see the above expression when <xsl:for-each select="item[3]"> would be better). Once you are inside a predicate [] the idea of the current XSLT context node becomes a little lost - because the XPath 'context' node becomes the node that is being passed to the predicate for testing. This is why in XSLT we have the current() function - so that within XPath expressions (especially within predicates) you can still access the XSLT context node. So say, for example, you wanted to look for all elements that had the same name as the current XSLT context node you would do something like... <xsl:for-each select="*[name() = name(current())]"> This can be done because the name() function can take a argument. If you were looking for an equivalent expression using the position() function it would look something like (but won't work!!)... <xsl:for-each select="*[position() = position(current()) - 1]"> *** CANNOT BE DONE!! *** The position() function cannot take an argument - so this is why you need, in XSLT, to store the position of the current XSLT context node for use with the predicate expression. Cheers Marrow "Jason Burr" <JasonBurr@d...> wrote in message news:B52C531A-8B6D-48B7-B9B7-570B0835CE20@m...... > I think what he was trying to say is this (if I'm wrong I hope he will > correct me) > > postion() can be assigned or it can be evaluated but it can't do both at the > same time. > > In other words > > 1. You can ask position() what it's value is > 2. You can tell position() what it's value is > 3. You can't ask it what it is and then tell it what it is at the same time. > > By assigning a variable you are asking it first and then telling it later > what it should be. > > The reason this seemed a wee bit nonsensical to me is that generally when > programming you have the ability to assign a value from the same value. > Because generally the statement to the right of a value assignment is > evaluated prior to its assignment on the left. > > so in programming generally this is a perfectly acceptable thing to do: > x = x + 1 > or > myObjectValue = myObjectValue - 1 > because its being read more like > > n = (x + 1) > x = n > > whereas with the predicate statement it is being read literally as > x = x + 1 > which can never be evaluated > > I think that is is because it is opening position() to accept a value and > therefore it has no value when requested after being opened for input. I'm > sure this is somehow by design and a perfectly good reason for it exists. > (late bound early bound language?) > > > "johndoe@d..." wrote: > > > I have seen and used the <xsl:variable name="PrevPos" > > select="position() - 1" /> through trial and error, but I have not really > > understood why exactly this is. I read the explanation provided by Marrow > > but it seems to have gone over my head. > > > > > > > > "Jason Burr" <JasonBurr@d...> wrote in message > > news:DD97D787-424F-4D74-B742-C69F5084D333@m...... > > > Marrow, > > > > > > Thanks simply assigning variable worked (never tried that because of all > > > the "no variable reassignment" griping) > > > > > > My thinking on the predicate was that the order of execution would be > > > > > > 1. evaluate value of the (current) position()-1 > > > 2. assign that value to position() > > > 3. retrive the node given the assigned position > > > > > > I guess my thinking was that = doesn't evaluate the truth a statement such > > > as > > > > > > x = x + 1 > > > > > > But rather > > > > > > (newvalue of x <--- (x - 1)) > > > > > > Anyway good stuff to know thanks again. > > > > > > "Marrow" wrote: > > > > > >> Hi Jason, > > >> > > >> > Not trying to accomplish any thing was just messing around and thought > > >> that > > >> > it might be a good way to check for the last record in a group during a > > >> loop. > > >> > Since I can't reassign variables and position() tells me where in a > > >> > loop I > > >> am > > >> > and position() can also be used to specify a node to look up it seemed > > >> (maybe > > >> > foolishly) that this was an easy way to know if the current node and > > >> previous > > >> > node for a given value match. > > >> > > >> The position() function when used **outside** a predicate will give you > > >> the > > >> position within the currently processed node-set (e.g. that selected by a > > >> @select on <xsl:apply-templates> or <xsl:for-each>). When the position() > > >> function is used **within** a predicate then it ruturns the index of the > > >> node within the nodes selected by the XPath expression to the left of the > > >> predicate. > > >> > > >> Your problem remains... > > >> > > >> > <xsl:when test="/foo/bar[position()=position()-1]/@attrib"> > > >> > > >> read the bit inside the [] predicate! ;) > > >> > > >> How can "position()=position()-1" ever evaluate to true??? It can't... x > > >> can never equal (x - 1)... complete impossibility! ;) > > >> > > >> Maybe one of those position()'s is the position prior to the predicate? > > >> In > > >> which case you would need to store one to a variable first, e.g something > > >> like... > > >> > > >> <xsl:for-each select="bar"> > > >> <xsl:variable name="curr-posn" select="position()"/> > > >> <xsl:choose> > > >> <xsl:when test="/foo/bar[position()=$curr-posn -1]/@attrib"> > > >> ... > > >> > > >> or even just calc the index, e.g. > > >> > > >> <xsl:for-each select="bar"> > > >> <xsl:variable name="prev-posn" select="position() - 1"/> > > >> <xsl:choose> > > >> <xsl:when test="/foo/bar[$prev-posn]/@attrib"> > > >> ... > > >> > > >> Cheers > > >> Marrow > > >> > > >> "Jason Burr" <JasonBurr@d...> wrote in message > > >> news:C68421B0-71EE-4519-B453-EEB0735C5504@m...... > > >> > Hey Marrow, > > >> > > > >> > Not trying to accomplish any thing was just messing around and thought > > >> that > > >> > it might be a good way to check for the last record in a group during a > > >> loop. > > >> > Since I can't reassign variables and position() tells me where in a > > >> > loop I > > >> am > > >> > and position() can also be used to specify a node to look up it seemed > > >> (maybe > > >> > foolishly) that this was an easy way to know if the current node and > > >> previous > > >> > node for a given value match. I am aware of Muenchian (you may have > > >> > helped > > >> me > > >> > out with that). > > >> > > > >> > Anyway the context of that example would have been in > > >> > > > >> > <foo> > > >> > <bar attrib='test'> > > >> > <bar attrib='test'> > > >> > <bar attrib='test2'> > > >> > </foo> > > >> > > > >> > <xsl:for-each select="bar"> > > >> > <xsl:choose> > > >> > <xsl:when test="/foo/bar[position()=position()-1]/@attrib"> > > >> > <xsl:value-of select="@attrib"/> > > >> > </xsl:when> > > >> > <xsl:otherwise> > > >> > <xsl:value-of select="@attrib"/> end of group > > >> > </xsl:otherwise> > > >> > </xsl:choose> > > >> > </xsl:for-each> > > >> > > > >> > Result expected > > >> > > > >> > test > > >> > test end of group > > >> > test2 > > >> > > > >> > Clearly I didn't mess with the keys or anything for grouping but this > > >> would > > >> > work if the xml was ordered or if using the Muenchian Technique. (that > > >> > is > > >> if > > >> > it evaluated like it does when using value-of) > > >> > > > >> > As far as it evaluating to nothing thats not completely true becuase if > > >> > I > > >> > hard code in the value of the position > > >> > > > >> > <xsl:value-of select="/foo/bar[position()=3]/@attrib"/> > > >> > > > >> > The the result would be > > >> > > > >> > test2 > > >> > > > >> > and if I do > > >> > > > >> > <xsl:value-of select="position()-1"/> > > >> > > > >> > I would get > > >> > > > >> > 0 > > >> > 1 > > >> > 2 > > >> > > > >> > So my general question was why would that not evaluate to the value of > > >> > the > > >> > node (which does exist) and return the value requested. Further if > > >> > there > > >> is > > >> > no way for this to work then is there another way to evaluate the same > > >> thing > > >> > (the previous node processed in a for-each) > > >> > > > >> > Thanks, > > >> > > > >> > Jason > > >> > > > >> > > > >> > > > >> > "Marrow" wrote: > > >> > > > >> > > Hi Jason, > > >> > > > > >> > > > But that this never returns a result > > >> > > > > > >> > > > <xsl:value-of select="/foo/bar[position()=position()-1]/@attrib"/> > > >> > > > > >> > > Of course it won't ever return anything... the predicate [] > > >> > > expression > > >> can > > >> > > never evalaute to true. > > >> > > > > >> > > > What I want to do here is look at the last record in a loop to see > > >> > > > if > > >> I am > > >> > > > at the end of a grouping (begininig of the next actually) > > >> > > > > >> > > Based on what you have described so far (but not seeing more of the > > >> > > XSLT > > >> and > > >> > > XML) I'd say it'is unlikely that your current method of doing > > >> > > grouping > > >> will > > >> > > work. There are a couple of ways of doing grouping in XSLT 1.0 - the > > >> > > Muenchian Technique and preceding-sibling technique. I'm sure if you > > >> post > > >> > > an example of what your are trying to do someone will be able to show > > >> you > > >> > > how to do these. > > >> > > > > >> > > Cheers > > >> > > Marrow > > >> > > http://www.marrowsoft.com - home of Xselerator (XSLT IDE and > > >> > > debugger) > > >> > > http://www.topxml.com/Xselerator > > >> > > > > >> > > > > >> > > "Jason Burr" <JasonBurr@d...> wrote in message > > >> > > news:3CEE074F-AD95-4124-ADD2-8DB46106D9BA@m...... > > >> > > > Can someone explain why doing this writes a number one less than > > >> > > > the > > >> > > current > > >> > > > position. > > >> > > > > > >> > > > <xsl:value-of select="position()-1"/> > > >> > > > > > >> > > > Doing this will display a specific positions value > > >> > > > > > >> > > > <xsl:value-of select="/foo/bar[position()=3]/@attrib"/> > > >> > > > > > >> > > > But that this never returns a result > > >> > > > > > >> > > > <xsl:value-of select="/foo/bar[position()=position()-1]/@attrib"/> > > >> > > > > > >> > > > What I want to do here is look at the last record in a loop to see > > >> > > > if > > >> I am > > >> > > > at the end of a grouping (begininig of the next actually) > > >> > > > > > >> > > > > >> > > > > >> > > > > >> > > >> > > >> > > > > > > | ||||||
| Company | Legal | Press | Partners | Careers | Sitemap | Contact Us | Altova Blog | Mobile | Full Site | |||
|
