Tricky XSL Problem — Determining Position in Complex Array
Question
<row>
<cell>Phrase 1</cell> #0
<check shuffle="False">
<option key="1"/> #1
<option key="0"/> #2
<option key="0"/> #3
<option key="0"/> #4
<option key="0"/> #5
<option key="0"/> #6
</check>
<cell>Phrase 2</cell> #7
<cell>Phrase 3</cell> #8
<check shuffle="False">
<option key="1"/> #9
<option key="0"/> #10
<option key="0"/> #11
<option key="0"/> #12
<option key="0"/> #13
<option key="0"/> #14
</check>
</row>
I've got the following quandary.
I need to find the "index" in the "row" tag for both cells and the each option.
How do I do this in XSL? Each cell counts as one and each "option" children tags in any siblings also count. I've labeled the "indexes" I would like to retrieve. I realize there will probably be one way for determining the index of a "cell" versus a "option" element.
I know a bit about XSL but just enough to get my in trouble and quite frustrated. Any help is appreciated.
Thanks as always SO!
Solution
Use xsl:number
:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="cell|option">
<xsl:call-template name="identity"/>
<xsl:variable name="vPosition">
<xsl:number count="cell|option" level="any" from="row" />
</xsl:variable>
<xsl:value-of select="$vPosition - 1"/>
</xsl:template>
</xsl:stylesheet>
With this input (more row
s):
<table>
<row>
<cell>Phrase 1</cell> #0
<check shuffle="False">
<option key="1"/> #1
<option key="0"/> #2
<option key="0"/> #3
<option key="0"/> #4
<option key="0"/> #5
<option key="0"/> #6
</check>
<cell>Phrase 2</cell> #7
<cell>Phrase 3</cell> #8
<check shuffle="False">
<option key="1"/> #9
<option key="0"/> #10
<option key="0"/> #11
<option key="0"/> #12
<option key="0"/> #13
<option key="0"/> #14
</check>
</row>
<row>
<cell>Phrase 1</cell> #0
<check shuffle="False">
<option key="1"/> #1
<option key="0"/> #2
<option key="0"/> #3
</check>
<cell>Phrase 2</cell> #4
<check shuffle="False">
<option key="1"/> #5
<option key="0"/> #6
</check>
<cell>Phrase 3</cell> #7
</row>
</table>
Output:
<table>
<row>
<cell>Phrase 1</cell>0 #0
<check shuffle="False">
<option key="1"></option>1 #1
<option key="0"></option>2 #2
<option key="0"></option>3 #3
<option key="0"></option>4 #4
<option key="0"></option>5 #5
<option key="0"></option>6 #6
</check>
<cell>Phrase 2</cell>7 #7
<cell>Phrase 3</cell>8 #8
<check shuffle="False">
<option key="1"></option>9 #9
<option key="0"></option>10 #10
<option key="0"></option>11 #11
<option key="0"></option>12 #12
<option key="0"></option>13 #13
<option key="0"></option>14 #14
</check>
</row>
<row>
<cell>Phrase 1</cell>0 #0
<check shuffle="False">
<option key="1"></option>1 #1
<option key="0"></option>2 #2
<option key="0"></option>3 #3
</check>
<cell>Phrase 2</cell>4 #4
<check shuffle="False">
<option key="1"></option>5 #5
<option key="0"></option>6 #6
</check>
<cell>Phrase 3</cell>7 #7
</row>
</table>
OTHER TIPS
Not sure I understand the question. Is it that in an XSLT stylesheet, while processing e.g. an <option>
element, you want to output its index among other <option>
and <cell>
elements? For that, you want <xsl:number>
.
Here's one way to solve it:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="/">
<indices>
<xsl:apply-templates select="//cell | //option" mode="index"/>
</indices>
</xsl:template>
<xsl:template match="*" mode="index">
<index pos="{ position() - 1 }">
<xsl:value-of select="concat( . , @key )"/>
</index>
</xsl:template>
</xsl:stylesheet>
I picked a special @mode
to highlight what's going on.
Note that position()
is 1-based and acts upon the "current node-set", which is wort looking up in an XSLT textbook.