Comparing current node to previous node with XSLT and XPath
April 30, 2008 1:47 PM   Subscribe

I need an XPath expression that will allow me (in XSLT) to compare the value of an XML element in one node with the value of another element in a preceding node.

So, given this faked up code:

<calendar>
<event>
<date>May 11</date>
<description>Mother's Day</description>
</event>
<event>
<date>May 12</date>
<description>Birthday</description>
</event>
<event>
<date>May 12</date>
<description>Board Meeting</description>
</event>
<calendar>

I want to use XSLT to return something that looks like this:

May 11
----------
Mother's Day

May 12
----------
Birthday
Board Meeting

The problem is, I can't figure out how to compare the value of date in the current node to date in the previous node.

I was trying
<xsl:if test="date != preceding-sibling::event/date"> but the problem is preceding-sibling is every sibling, and it defaults to the first sibling. I want the exact previous node -- if you're on X event node, compare the value of date to the value of date in X-1 event node. Since the total number of possible event nodes could be anywhere from 1 to infinite, I can't just write code that goes event[3] vs event[2].

I know there's a simple way to do this, but I've just about exhausted my Google-fu. Ideas?
posted by dw to Computers & Internet (5 answers total) 2 users marked this as a favorite
 
Forgive me if I'm misunderstanding, but have you tried something equivalent to (forgive pseudo-code) -

for-each //event
  if not(date/value() = ../event[position()-1]/date/value())
    print date

? Assuming that's what you're looking to do. You could alternatively do something starting with for-each(distinct-values(//date/value())), I think, and come at it that way. That would have the advantage of not depending on the order of events.
posted by thoughtless at 2:10 PM on April 30, 2008


preceding-sibling ought to work, it's a reverse axis so the nodes are returned in reverse order. I think you just need to add a [1] so you're comparing only against one node instead of against all of the preceding siblings (which will likely succeed since the '!=' test will succeed ANY node on the left is not-equal to ANY node on the right). That is:

date != preceding-sibling::event[1]/date

That said, I am just spouting this off the top of my head so I can only hope I'm right!
posted by Khalad at 2:40 PM on April 30, 2008


This should do it!
posted by gsteff at 3:03 PM on April 30, 2008


FYI, the preserve-space accomplishes nothing... xsl:text was easier.
posted by gsteff at 3:04 PM on April 30, 2008


Arrgh. It was the "reverse axis" part of preceding-sibling I was missing. Thank you!
posted by dw at 4:55 PM on April 30, 2008


« Older How to use external installer parameters?   |   Comcast DVR w/ Tivo -- any good, in 2008? Newer »
This thread is closed to new comments.