If you can iterate over all keys of the stat entries (from your comments, the keys are all item_id
+vehicle_id
values pairs), it should be pretty easy to aggregate all the attributes that belong to each key in one go.
From your expected output, it appears that for every key, there is exactly one <weapon_stat>
element with stat_name='weapon_fire_count'
. Given that this is correct, you'll easily get all item_id
values by iterating over these <weapon_stat>
elements:
<xsl:for-each select="stats/weapon_stat_list/weapon_stat[@stat_name='weapon_fire_count']" >
From these elements, it is straightforward to generate the output fields Item ID, Vehicle ID, and Fire Count. For the other three fields, you can select the value from the appropriate sibling with the following (a bit more advanced) XPath expression:
<xsl:value-of select="../weapon_stat[@stat_name='weapon_hit_count' and @item_id=current()/@item_id and @vehicle_id=current()/@vehicle_id]/@value" />
The trick is to compare the @item_id
and @vehicle_id
of the respective context nodes (these are all siblings: ../weapon_stat
) with the @item_id
and @vehicle_id
of the current node (which is the node selected by the for-each
above).
All in all, you want to replace the inner for-each
of your XSL file with this:
<xsl:for-each select="stats/weapon_stat_list/weapon_stat[@stat_name='weapon_fire_count']" >
<ROW>
<COL><DATA><xsl:value-of select="$cid" /></DATA></COL>
<COL><DATA><xsl:value-of select="@item_id" /></DATA></COL>
<COL><DATA><xsl:value-of select="@vehicle_id" /></DATA></COL>
<COL><DATA><xsl:value-of select="@value" /></DATA></COL>
<COL><DATA><xsl:value-of select="../weapon_stat[@stat_name='weapon_hit_count' and @item_id=current()/@item_id and @vehicle_id=current()/@vehicle_id]/@value" /></DATA></COL>
<COL><DATA><xsl:value-of select="../weapon_stat[@stat_name='weapon_play_time' and @item_id=current()/@item_id and @vehicle_id=current()/@vehicle_id]/@value" /></DATA></COL>
<COL><DATA><xsl:value-of select="../weapon_stat[@stat_name='weapon_score' and @item_id=current()/@item_id and @vehicle_id=current()/@vehicle_id]/@value" /></DATA></COL>
</ROW>
</xsl:for-each>
Note: I omitted the MODID
and RECORDID
counters because there is no efficient solution to add them in this transformation. However, it is straightforward to take the result of this transformation and add the counters through a second XSL transformation.
Update: In the pastebin example you gave in a comment, it seems that not every key has a weapon_fire_count
stat. So instead of iterating only over these stat entries, you need to iterate over all stats, and omit the output if there was already a preceding sibling with the same key:
<xsl:for-each select="stats/weapon_stat_list/weapon_stat" >
<xsl:if test="not(boolean(preceding-sibling::weapon_stat[@item_id=current()/@item_id and @vehicle_id=current()/@vehicle_id]))">
<ROW >
<COL><DATA><xsl:value-of select="$cid" /></DATA></COL>
<COL><DATA><xsl:value-of select="@item_id" /></DATA></COL>
<COL><DATA><xsl:value-of select="@vehicle_id" /></DATA></COL>
<COL><DATA><xsl:value-of select="../weapon_stat[@stat_name='weapon_fire_count' and @item_id=current()/@item_id and @vehicle_id=current()/@vehicle_id]/@value" /></DATA></COL>
<COL><DATA><xsl:value-of select="../weapon_stat[@stat_name='weapon_hit_count' and @item_id=current()/@item_id and @vehicle_id=current()/@vehicle_id]/@value" /></DATA></COL>
<COL><DATA><xsl:value-of select="../weapon_stat[@stat_name='weapon_play_time' and @item_id=current()/@item_id and @vehicle_id=current()/@vehicle_id]/@value" /></DATA></COL>
<COL><DATA><xsl:value-of select="../weapon_stat[@stat_name='weapon_score' and @item_id=current()/@item_id and @vehicle_id=current()/@vehicle_id]/@value" /></DATA></COL>
</ROW>
</xsl:if>
</xsl:for-each>