Reputation: 5165
I want to add <LineNum>[number]</LineNum>
in output and LineNum has to start from '1' again if we have different value in <cell num="4">
Source xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<table>
<sheet name="Notification" num="1">
<row num="1">
<cell num="1">IBD</cell>
<cell num="2">YES</cell>
<cell num="3">6600027830(010000)</cell>
<cell num="4">800015001</cell>
</row>
<row num="2">
<cell num="1">IBD</cell>
<cell num="2">YES</cell>
<cell num="3">6600027830(010000)</cell>
<cell num="4">800015001</cell>
</row>
<row num="3">
<cell num="1">IBD</cell>
<cell num="2">YES</cell>
<cell num="3">6600027831(010000)</cell>
<cell num="4">800015002</cell>
</row>
<row num="4">
<cell num="1">IBD</cell>
<cell num="2">YES</cell>
<cell num="3">6600027831(010000)</cell>
<cell num="4">800015002</cell>
</row>
<row num="5">
<cell num="1">IBD</cell>
<cell num="2">YES</cell>
<cell num="3">6600027831(010000)</cell>
<cell num="4">800015002</cell>
</row>
</sheet>
</table>
so will be in this case:
<cell num="4">800015001</cell>
<LineNum>1</LineNum>
<cell num="4">800015001</cell>
<LineNum>2</LineNum>
<!-- cell num="4" different from previous, start LineNum from 1 -->
<cell num="4">800015002</cell>
<LineNum>1</LineNum>
<cell num="4">800015002</cell>
<LineNum>2</LineNum>
<cell num="4">800015002</cell>
<LineNum>3</LineNum>
I could add global var, assign cell num="4" to it and then check if current value is same as global var, if not - start LineNum from 1 again and reassign global var. Sadly XSLT doesn't provide reassigning.
What can I do?
UPD: was trying to somehow modify example from other question XSL: Counting Previous Unique Siblings, but no luck..
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<!-- don't copy whitespace -->
<xsl:template match="text()"/>
<xsl:template match="row/cell[@num=4]">
<xsl:variable name="roles-so-far" select=". | preceding::row/cell[@num=4]"/>
<xsl:value-of select="count($roles-so-far)"/>
<xsl:value-of select="' '"/>
<xsl:value-of select="."/>
<!-- Only select the first instance of each ROLE name -->
<xsl:variable name="roles-so-far-unique"
select="$roles-so-far[not(. = preceding-sibling::row/cell[@num=4])]"/>
<xsl:apply-templates select="/"/>
<xsl:text> </xsl:text>
<xsl:value-of select="count($roles-so-far-unique)"/>
<xsl:text>
</xsl:text> <!-- linefeed -->
</xsl:template>
</xsl:stylesheet>
Upvotes: 0
Views: 385
Reputation: 167401
With the question being tagged as xslt-2.0 you can easily use for-each-group group-adjacent
:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="sheet">
<xsl:copy>
<xsl:for-each-group select="row" group-adjacent="cell[@num = 4]">
<xsl:apply-templates select="current-group()"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="row">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
<LineNum><xsl:value-of select="position()"/></LineNum>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When I apply above code with Saxon 9.4 to your input sample I get the following result:
<table>
<sheet>
<row num="1">
<cell num="1">IBD</cell>
<cell num="2">YES</cell>
<cell num="3">6600027830(010000)</cell>
<cell num="4">800015001</cell>
<LineNum>1</LineNum>
</row>
<row num="2">
<cell num="1">IBD</cell>
<cell num="2">YES</cell>
<cell num="3">6600027830(010000)</cell>
<cell num="4">800015001</cell>
<LineNum>2</LineNum>
</row>
<row num="3">
<cell num="1">IBD</cell>
<cell num="2">YES</cell>
<cell num="3">6600027831(010000)</cell>
<cell num="4">800015002</cell>
<LineNum>1</LineNum>
</row>
<row num="4">
<cell num="1">IBD</cell>
<cell num="2">YES</cell>
<cell num="3">6600027831(010000)</cell>
<cell num="4">800015002</cell>
<LineNum>2</LineNum>
</row>
<row num="5">
<cell num="1">IBD</cell>
<cell num="2">YES</cell>
<cell num="3">6600027831(010000)</cell>
<cell num="4">800015002</cell>
<LineNum>3</LineNum>
</row>
</sheet>
</table>
Upvotes: 1