XSLT: Loop selecting two elements at a time

xslt

Solution

Sure there is a generic way:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

  <xsl:template match="row">
    <set>
      <xsl:apply-templates select="
        col[position() mod 2 = 1 and following-sibling::col]
      " />
    </set>
  </xsl:template>

  <xsl:template match="col">
    <point x="{text()}" y="{following-sibling::col[1]/text()}" />
  </xsl:template>

</xsl:stylesheet>

Output for me:

<set>
  <point x="0" y="0" />
  <point x="1" y="1" />
</set>

Problem

I have a bunch of xml documents where the author chose to represent a set of cartesian points like this: ``` <row index="0"> <col index="0">0</col> <col index="1">0</col> <col index="2">1</col> <col index="3">1</col> </row> ``` This would be equal to the points (0,0) and (1,1). I want to rewrite this as ``` <set> <point x="0" y="0"/> <point x="1" y="1"/> </set> ``` However, I cannot figure out how to create this in XSLT, other than hardcoding for each possible case - for instance for a 4-point set: ``` <set> <point> <xsl:attribute name="x"><xsl:value-of select="col[@index = 0]"/></xsl:attribute> <xsl:attribute name="y"><xsl:value-of select="col[@index = 1]"/></xsl:attribute> </point> <point> <xsl:attribute name="x"><xsl:value-of select="col[@index = 1]"/></xsl:attribute> <xsl:attribute name="y"><xsl:value-of select="col[@index = 2]"/></xsl:attribute> </point> ... ``` There must be a better way to do this? To summarize, I want to create elements like `<point x="..." y="..."/>`, where x and y are the even/odd-indexed `col` elements.

Original source