Generating a sequence in XSLT

I came upon a requirement where I needed to generate a sequence in XLST. Requirement is as below:
Input xml say an Order has multiple order line items and input does not contain order line number, however in output, a line number starting from 1 was required in a sequence.

Sample input :
<Order xmlns="http://www.example.org">
<OrderNumber>1</OrderNumber>
<CustomerNumber>CUST001</CustomerNumber>
<OrderLine>
<PartNumber>PART1</PartNumber>
<Qty>5</Qty>
</OrderLine>
<OrderLine>
<PartNumber>PART2</PartNumber>
<Qty>1</Qty>
</OrderLine>
<OrderLine>
<PartNumber>PART3</PartNumber>
<Qty>11</Qty>
</OrderLine>
</Order>

Expected output :
<?xml version = '1.0' encoding = 'UTF-8'?>
<ns0:Order xmlns:ns0="http://www.example.org">
<ns0:OrderNumber>1</ns0:OrderNumber>
<ns0:CustomerNumber>CUST001</ns0:CustomerNumber>
<ns0:OrderLine>
<ns0:OrderLineNumber>1</ns0:OrderLineNumber>
<ns0:PartNumber>PART1</ns0:PartNumber>
<ns0:Qty>5</ns0:Qty>
</ns0:OrderLine>
<ns0:OrderLine>
<ns0:OrderLineNumber>2</ns0:OrderLineNumber>
<ns0:PartNumber>PART2</ns0:PartNumber>
<ns0:Qty>1</ns0:Qty>
</ns0:OrderLine>
<ns0:OrderLine>
<ns0:OrderLineNumber>3</ns0:OrderLineNumber>
<ns0:PartNumber>PART3</ns0:PartNumber>
<ns0:Qty>11</ns0:Qty>
</ns0:OrderLine>
</ns0:Order>

As we can not have counter in for loop, we might have to implement it using a recursive template. Please refer – For Loop with counter in XSLT
And then I came across an xslt element called xsl:number, which can be used determine position of node in source. I tried same. Below is working XSLT using xsl:number :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ns0="http://www.example.org"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="xsd xsi xsl ns0"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
>
<xsl:template match="/">
<ns0:Order>
<ns0:OrderNumber>
<xsl:value-of select="/ns0:Order/ns0:OrderNumber"/>
</ns0:OrderNumber>
<ns0:CustomerNumber>
<xsl:value-of select="/ns0:Order/ns0:CustomerNumber"/>
</ns0:CustomerNumber>
<xsl:for-each select="/ns0:Order/ns0:OrderLine">
<ns0:OrderLine>
<ns0:OrderLineNumber>
<xsl:number count="/ns0:Order/ns0:OrderLine" level="any" format="1"/>
</ns0:OrderLineNumber>
<ns0:PartNumber>
<xsl:value-of select="ns0:PartNumber"/>
</ns0:PartNumber>
<ns0:Qty>
<xsl:value-of select="ns0:Qty"/>
</ns0:Qty>
</ns0:OrderLine>
</xsl:for-each>
</ns0:Order>
</xsl:template>
</xsl:stylesheet>

Here xsl:number is used to get position of OrderLine in source and used it as sequence number. Level =”any” means, no matter at what level in source it occurs, consider the element. 

It also has other optional parameter,

<xsl:number
count="expression"
level="single|multiple|any"
from="expression"
value="expression"
format="formatstring"
lang="languagecode"
letter-value="alphabetic|traditional"
grouping-separator="character"
grouping-size="number"/>

For more details on each parameter, please refer w3chools xslNumber

Leave Comment

Your email address will not be published. Required fields are marked *