Reputation: 449
I am trying to implement some php code logic, into XSLT.
The xml structure looks like
Input:
<parent>
<child>
<id>1</id>
<value>11</value>
</child>
<child>
<id>2</id>
<value>22</value>
</child>
<child>
<id></id>
<value>22</value>
</child>
<child>
<id></id>
<value>00</value>
</child>
<child>
<id></id>
<value>00</value>
</child>
<parent>
The sudo code in php (logic) I am trying to implement in XSLT is as follows:
var Index = 1;
for each "child"{
if( "id" is not empty ){
Index += "id" + 1;
}else{
if( previous "value" == current "value" ){
"id" = Index;
Index++;
}else{
"id" = 1;
Index = 2;
}
}
}
As I understand in XSLT we can't have a counter/variable that we can update on each iteration. I believe I can use the preceding-sibling
to compare the previous value with the current value, but how to calculate the index at that point? I can use XSLT 2.0, if that makes it easier/simpler.
Any ideas suggestions?
The output after the transform should look as follows:
Output:
<parent>
<child>
<id>1</id>
<value>11</value>
</child>
<child>
<id>2</id>
<value>22</value>
</child>
<child>
<id>6</id> <!-- "id" = "Index" calculated so far, since current value (22) = previous value (22) -->
<value>22</value>
</child>
<child>
<id>1</id> <!-- "id" = 1 since current value (00) != previous value (22) -->
<value>00</value>
</child>
<child>
<id>2</id> <!-- "id" = "Index" calculated so far, since currnet value (00) = previous value (00) -->
<value>00</value>
</child>
<parent>
Upvotes: 1
Views: 466
Reputation: 167716
Here is an attempt using XSLT 3 and xsl:iterate
:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="parent">
<xsl:copy>
<xsl:iterate select="child">
<xsl:param name="index" select="1"/>
<xsl:param name="previous-value" select="()"/>
<xsl:variable name="value" select="value"/>
<xsl:variable name="id"
select="(id[has-children()], if ($value = $previous-value) then $index else 1)[1]"/>
<xsl:variable name="index"
select="if (id[has-children()])
then $index + $id + 1
else if ($value = $previous-value)
then $index + 1
else 2"/>
<xsl:apply-templates select=".">
<xsl:with-param name="id" select="$id" tunnel="yes"/>
</xsl:apply-templates>
<xsl:next-iteration>
<xsl:with-param name="index" select="$index"/>
<xsl:with-param name="previous-value" select="$value"/>
</xsl:next-iteration>
</xsl:iterate>
</xsl:copy>
</xsl:template>
<xsl:template match="id[not(has-children())]">
<xsl:param name="id" tunnel="yes"/>
<xsl:copy>{$id}</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1