Reputation: 81
I have following XML .. I want to get the count of 'step' nodes from current 'step' node to the preceding step which has node event with value 'DoubleClick'.
<?xml version="1.0" encoding="utf-8"?>
<gps>
<step>
<event>DoubleClick</event>
</step>
<step>
<event>click</event>
</step>
<step>
<event>click</event>
</step>
<step>
<event>click</event>
</step>
<step>
<event>DoubleClick</event>
</step>
<step>
<event>click</event>
</step>
<step>
<event>click</event>
</step>
<step>
<event>click</event>
</step>
<step>
<event>DoubleClick</event>
</step>
</gps>
Upvotes: 2
Views: 1849
Reputation: 5432
You can use the following xpath when the current node is step
:
count(preceding-sibling::step[generate-id(preceding-sibling::step[event = 'DoubleClick'][1]) = generate-id(current()/preceding-sibling::step[event = 'DoubleClick'][1])])
EDIT:
And if you want to count even the step
with DoubleClick, use this xpath:
count(preceding-sibling::step[event = 'DoubleClick'][1]) * (count(preceding-sibling::step[generate-id(preceding-sibling::step[event = 'DoubleClick'][1]) = generate-id(current()/preceding-sibling::step[event = 'DoubleClick'][1])]) + 1)
Upvotes: 0
Reputation: 116993
There are several ways you could accomplish this, here's one:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/gps">
<xsl:copy>
<xsl:for-each select="step">
<xsl:copy>
<xsl:attribute name="x">
<xsl:value-of select="position() - count(preceding-sibling::step[event='DoubleClick'][1]/preceding-sibling::step)" />
</xsl:attribute>
<xsl:copy-of select="event" />
</xsl:copy>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Note that while simple to implement, it is a bit CPU-intensive. For a large amount of steps, you may prefer something like:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="event">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
<x>
<xsl:number from="step[event='DoubleClick']" level="any" />
</x>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1