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?
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?
Best answer: 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
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
FYI, the preserve-space accomplishes nothing... xsl:text was easier.
posted by gsteff at 3:04 PM on April 30, 2008
posted by gsteff at 3:04 PM on April 30, 2008
Response by poster: 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
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.
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