XSLT - previous nodes across ancestors, getting wrong count
I have some XML like the following:
<layout>
<table>
<tbody>
<tr>
<ref id="stock1" class="pile stock"/>
</tr>
<tr>
<ref id="cascade1" class="pile"/>
<ref id="cascade2" class="pile"/>
</tr>
</tbody>
</table>
</layout>
I'm trying to get a count of how many cards have been used by the preceding ref
s, because each ref
points to another tag elsewhere in the document that has card
children.
<xsl:variable name="curPos" select="position()"/>
<!-- Layout could change, not guaranteed previous ref is in same parent node as
current ref, or at the same depth. -->
<xsl:variable name="prevRefID"
select="/layout//*/ref[position() < $curPos]/@id"/>
<xsl:variable name="numCardsPrevUsed"
select="count(/cardHolder/*[@id = $prevRefID]/card)"/>
The problem is I'm not always getting correct previously-used-card counts. When at ref
'stock1', it correctly says 0 cards have been used so far, but when it gets to ref
'cascade1', it still says 0 cards have been used even though ref
'stock1' uses 24 cards. Then when it gets to ref
'cascade2', it suddenly says that 25 cards have been used, which is correct (24 in 'stock1' + 1 in 'cascade1'). Why is the number of previously used cards incorrect at ref
'cascade1'?
Edit: yikes, here's some sample XML:
<game name="Klondike">
<layout>
<table>
<tbody>
<tr>
<ref id="stock1" class="pile stock"/>
<ref id="waste1" colspan="2" class="empty-pile"/>
<ref id="foundation1" class="empty-pile"/>
<ref id="foundation2" class="empty-pile"/>
<ref id="foundation3" class="empty-pile"/>
<ref id="foundation4" class="empty-pile"/>
</tr>
<tr>
<ref id="cascade1" class="pile"/>
<ref id="cascade2" class="pile"/>
<ref id="cascade3" class="pile"/>
<ref id="cascade4" class="pile"/>
<ref id="cascade5" class="pile"/>
<ref id="cascade6" class="pile"/>
<ref id="cascade7" class="pile"/>
</tr>
</tbody>
</table>
</layout>
<state id="start">
<foundation id="foundation1" />
<foundation id="foundation2" />
<foundation id="foundation3" />
<foundation id="foundation4" />
<cascade id="cascade1">
<card suit="random" number="random" faceup="true"/>
</cascade>
<cascade id="cascade2">
<card suit="random" number="random"/>
<card suit="random" number="random" faceup="true"/>
</cascade>
...other cascades...
<waste id="waste1" />
<stock id="stock1">
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="ra开发者_如何学运维ndom" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
<card suit="random" number="random"/>
</stock>
</state>
</game>
I think that all depends by current template context where your code fragment is placed and the consequent incorrect use of position()
. The above fragment works fine if you are iterating on ref
nodes, not if you are matching on them.
For instance in this situation:
<xsl:template match="//ref">
<!-- your fragment -->
</xsl:template>
your code will never work, because postion()
is not obviously progressive. You should use something like:
<xsl:variable name="curPos"
select="count(../preceding-sibling::tr/ref
| preceding-sibling::ref)"/>
<xsl:value-of select="$curPos"/>
<xsl:variable name="prevRefID"
select="//layout//*/ref
[count(preceding-sibling::ref) < $curPos]/@id"/>
or better, change the template context so that you can use position()
.
精彩评论