How to get last 2 nodes previous specific node? - xslt

This is my xml:
<Line>
<Item>
<Id>1</Id>
<Name>A</Name>
<Unit>AA</Unit>
<Value>5</Value>
</Item>
</Line>
<Line>
<Item>
<Id>2</Id>
<Name>B</Name>
<Unit>Test</Unit>
<Value>5</Value>
</Item>
</Line>
<Line>
<Item>
<Id>3</Id>
<Name>C</Name>
<Unit>AA</Unit>
<Value>5</Value>
</Item>
</Line>
<Line>
<Item>
<Id>4</Id>
<Name>D</Name>
<Unit>AA</Unit>
<Value>5</Value>
</Item>
</Line>
<Line>
<Item>
<Id>5</Id>
<Name>E</Name>
<Unit>AA</Unit>
<Value>5</Value>
</Item>
</Line>
How to get all nodes which are at first and second position after nodes with Unit= Test. In this case, node with Id= 2 have Unit = Test so I want to display nodes with Id = 3 and Id = 4.
Thanks

The expression you want is this...
<xsl:copy-of select="//Line[Item/Unit='Test']/following-sibling::Line[position() <= 2]" />
This will work regardless of what the current node is.
Alternatively, you could split it out in to templates. For example
<xsl:template match="/*">
<xsl:apply-templates select="//Line[Item/Unit='Test']" />
</xsl:template>
<xsl:template match="Line">
<xsl:copy-of select="following-sibling::Line[position() <= 2]" />
</xsl:template>
If you want to get all nodes except 3 and 4, try this expression instead
<xsl:copy-of select="//Line[not(preceding-sibling::Line[position() <= 2][Item/Unit = 'Test'])]" />

Related

XSLT selecting unique values using for-each

I want to extract unique values of element i tried for-each with following-sibling but it is not working
Main problem is that I don't know how to get distinct values using XSLT 1.0 or 2.0
Here is Source XML example i am using
<Items>
<Item>
<Itemno>112</Itemno>
<itemname>abc</itemname>
<qun>5</qun>
<loc>US</loc>
</Item>
</Items>
<Items>
<Item>
<Itemno>112</Itemno>
<itemname>abc</itemname>
<qun>6</qun>
<loc>UK</loc>
</Item>
</Items>
<Items>
<Item>
<Itemno>112</Itemno>
<itemname>abc</itemname>
<qun>11</qun>
<loc>GER</loc>
</Item>
</Items>
<Items>
<Item>
<Itemno>114</Itemno>
<itemname>lkj</itemname>
<qun>1</qun>
<loc>IND</loc>
</Item>
</Items>
Required Output
<Order>
<Item>
<Itemno>112</Itemno>
<itemname>abc</itemname>
<Desc>
<qun>5</qun>
<loc>US</loc>
</Desc>
<Desc>
<qun>6</qun>
<loc>UK</loc>
</Desc>
<Desc>
<qun>11</qun>
<loc>GER</loc>
</Desc>
</Item>
<Item>
<Itemno>114</Itemno>
<itemname>lkj</itemname>
<Desc>
<qun>1</qun>
<loc>IND</loc>
</Desc>
</Item>
</Order>
In xslt 2.0 you can for grouping by Itemno use for-each-group. As example you can use this code
<xsl:template match="Items">
<Order>
<xsl:for-each-group select="//Item" group-by="Itemno">
<Item>
<xsl:copy-of select="Itemno"/>
<xsl:copy-of select="itemname"/>
<xsl:for-each select="current-group()">
<Desc>
<xsl:copy-of select="qun"/>
<xsl:copy-of select="loc"/>
</Desc>
</xsl:for-each>
</Item>
</xsl:for-each-group>
</Order>
</xsl:template>
The result of it is xml that you need

xslt 1 : check if node contains any value from list

I need to tranform a XML document from one format to a other, and that is all dandy. Now the hard part is that I need to check all lines for a status code, and need to return true/false depend if any code element have any of this codes.
<xml>
<line>
<id>1</id>
<code>109</code>
</line>
<line>
<id>2</id>
<code>065</code>
</line>
<line>
<id>3</id>
<code>405</code>
</line>
<line>
<id>4</id>
<code>101</code>
</line>
</xml>
The document I tranform to keep a copy of all line element, but have a extra field, where is set to true/false depend if the any code is in the list.
So I need to compare this list of data to every code and return true if just one of them is in the list
"101","102","103","104","105","106","107","108","109","110","111"
Is there any fix mode to make this so I don't need 11 compare stament ?
Ohh and the output look some thing like
<System>
<Route>true</Route> <!-- will be false if the <code> from the first document is not in the list of elements -->
<Status>
<ID>1</ID>
<Code>109</Code>
</Status>
<Status>
<ID>2</ID>
<Code>065</Code>
</Status>
<Status>
<ID>3</ID>
<Code>405</Code>
</Status>
<Status>
<ID>4</ID>
<Code>101</Code>
</Status>
<System>
This transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pCodeList" select="'101,102,103,104,105,106,107,108,109,110,111'"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<System>
<Route>
<xsl:value-of select=
"boolean(/*/*/code
[contains(concat(',', $pCodeList, ','), concat(',', ., ',')
)
]
)"/>
</Route>
<xsl:apply-templates/>
</System>
</xsl:template>
<xsl:template match="line">
<Status><xsl:apply-templates/></Status>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<xml>
<line>
<id>1</id>
<code>109</code>
</line>
<line>
<id>2</id>
<code>065</code>
</line>
<line>
<id>3</id>
<code>405</code>
</line>
<line>
<id>4</id>
<code>101</code>
</line>
</xml>
produces the wanted, correct result:
<System>
<Route>true</Route>
<Status>
<id>1</id>
<code>109</code>
</Status>
<Status>
<id>2</id>
<code>065</code>
</Status>
<Status>
<id>3</id>
<code>405</code>
</Status>
<Status>
<id>4</id>
<code>101</code>
</Status>
</System>
When the same transformation (above) is applied on this XML document:
<xml>
<line>
<id>1</id>
<code>509</code>
</line>
<line>
<id>2</id>
<code>065</code>
</line>
<line>
<id>3</id>
<code>405</code>
</line>
<line>
<id>4</id>
<code>501</code>
</line>
</xml>
it again produces the wanted, correct result:
<System>
<Route>false</Route>
<Status>
<id>1</id>
<code>509</code>
</Status>
<Status>
<id>2</id>
<code>065</code>
</Status>
<Status>
<id>3</id>
<code>405</code>
</Status>
<Status>
<id>4</id>
<code>501</code>
</Status>
</System>

Perform an XSLT Logic

input:
<Move-Afile>
<Afile>
<Item>
<suppliercode>1</suppliercode>
<PackNumber>1234</PackNumber>
<Item85>
<Quantity>12</Quantity>
</Item85>
</Item>
<Item>
<suppliercode>2</suppliercode>
<PackNumber>567</PackNumber>
<Item85>
<Quantity>3</Quantity>
</Item85>
</Item>
<Item>
<suppliercode>1</suppliercode>
<PackNumber>567</PackNumber>
<Item85>
<Quantity>8</Quantity>
</Item85>
</Item>
<Item>
<suppliercode>3</suppliercode>
<PackNumber>126</PackNumber>
<Item85>
<Quantity>11</Quantity>
</Item85>
</Item>
<Item>
<suppliercode>4</suppliercode>
<PackNumber>876</PackNumber>
<Item85>
<Quantity>32</Quantity>
</Item85>
</Item>
</Afile>
</Move-Afile>
xslt:
i need the solution like the xsl should contain for-each structure like below.
If supplier codes are equal then we have to sum the quantity values of those nodes,otherwise directly map the quantity value.
<xsl:for-each select="/Move-Afile/Afile/Item">
<xsl:choose>
<xsl:when test="suppliercode=suppliercode>
<xsl:value-of select=sum(Quantity)"/><!-- sum of quantity where nodes have equal supplier code-->
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="Quantity"/><!-- map directly the quantity value-->
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
output:
<A>
<target>
<Item>
<Quantity>20</Quantity>
</Item>
<Item>
<Quantity>3</Quantity>
</Item>
<Item>
<Quantity>20</Quantity>
</Item>
<Item>
<Quantity>11</Quantity>
</Item>
<Item>
<Quantity>32</Quantity>
</Item>
</target>
</A>
You don't really need an xsl:choose here, just a single sum statement to sum all Quantity elements for Item elements with the same suppliercode (which include the current node you are on).
<xsl:value-of select="sum(//Item[suppliercode = current()/suppliercode]/Item85/Quantity)"/>
However, it would be more efficient to make use of a key to look for matching Item elements:
<xsl:key name="Item" match="Item" use="suppliercode" />
Then the sum statement is simplified to this
<xsl:value-of select="sum(key('Item', suppliercode)/Item85/Quantity)"/>
You might also like to consider using the XSLT identity transform in building your output XML, as this would be more flexible. You would probably only need a template matching the Quantity element in this case
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="Item" match="Item" use="suppliercode" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Quantity">
<xsl:copy>
<xsl:value-of select="sum(key('Item', ../../suppliercode)/Item85/Quantity)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When applied to your XML, the following is output
<Move-Afile>
<Afile>
<Item>
<suppliercode>1</suppliercode>
<PackNumber>1234</PackNumber>
<Item85>
<Quantity>20</Quantity>
</Item85>
</Item>
<Item>
<suppliercode>2</suppliercode>
<PackNumber>567</PackNumber>
<Item85>
<Quantity>3</Quantity>
</Item85>
</Item>
<Item>
<suppliercode>1</suppliercode>
<PackNumber>567</PackNumber>
<Item85>
<Quantity>20</Quantity>
</Item85>
</Item>
<Item>
<suppliercode>3</suppliercode>
<PackNumber>126</PackNumber>
<Item85>
<Quantity>11</Quantity>
</Item85>
</Item>
<Item>
<suppliercode>4</suppliercode>
<PackNumber>876</PackNumber>
<Item85>
<Quantity>32</Quantity>
</Item85>
</Item>
</Afile>
</Move-Afile>
If you do want to change or remove other elements, just add separate templates for each case accordingly.

XSLT Grouping elements inside two siblings

I'm trying to wrap my head around this and I think the easiest way to explain it is to just show you, below. I've seen this but it doesn't always apply due to the fact I have standalone items also at the end which would match.
The seemingly tricky part is Whatever3 to Whatever6, and then Whatever7 and Whatever8, then finally the new position of Whatever9 - they need to be grouped and the original sequence maintained. (Ignore my naming, there is no way to use xsl:sort)
I've considered xsl:for-each with xsl:if inside, but issue is you can't guarantee how many "groups" vs "non-group" items there are.
Thanks!
XML
<root>
<item>
<position>1</position>
<label>Whatever1</label>
</item>
<item>
<position>2</position>
<label>Whatever2</label>
</item>
<item>
<position>3</position>
<label>Whatever3</label>
<marker id="unique1">start_group</marker>
</item>
<item>
<position>4</position>
<label>Whatever4</label>
</item>
<item>
<position>5</position>
<label>Whatever5</label>
</item>
<item>
<position>6</position>
<label>Whatever6</label>
<marker>last_in_group</marker>
</item>
<item>
<position>7</position>
<label>Whatever7</label>
<marker id="unique2">start_group</marker>
</item>
<item>
<position>8</position>
<label>Whatever8</label>
<marker>last_in_group</marker>
</item>
<item>
<position>9</position>
<label>Whatever9</label>
</item>
</root>
Result
<structure>
<item>
<position>1</position>
<label>Whatever1</label>
</item>
<item>
<position>2</position>
<label>Whatever2</label>
</item>
<group position="3" id="unique1">
<item>
<position>1</position>
<label>Whatever3</label>
</item>
<item>
<position>2</position>
<label>Whatever4</label>
</item>
<item>
<position>3</position>
<label>Whatever5</label>
</item>
<item>
<position>4</position>
<label>Whatever6</label>
</item>
</group>
<group position="4" id="uniqueid2">
<item>
<position>1</position>
<label>Whatever7</label>
</item>
<item>
<position>2</position>
<label>Whatever8</label>
</item>
</group>
<item>
<position>**5**</position>
<label>Whatever9</label>
</item>
</structure>
======================
Here is what I have so far, the only problem I have (besides it being messy) is Whatever4 and Whatever5 are showing up outside the Group.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="root">
<structure>
<xsl:apply-templates select="item[not(marker)] | item[marker='start_group']"/>
</structure>
</xsl:template>
<xsl:template match="item[marker='start_group']">
<group>
<xsl:variable name="currentPosition" select="number(position/text())"/>
<xsl:variable name="lastGroup" select="count(following-sibling::*[local-name() = 'item' and marker='last_in_group'][1]/preceding-sibling::*) + 1"/>
<xsl:attribute name="position">
<xsl:value-of select="$currentPosition"/>
</xsl:attribute>
<xsl:attribute name="id">
<xsl:value-of select="marker/#id"/>
</xsl:attribute>
<item>
<position><xsl:value-of select="number(position/text()) - $currentPosition + 1"/></position>
<label><xsl:value-of select="label/text()"/></label>
</item>
<!-- position() gets reset in for-loop, so need to adjust with outer position -->
<xsl:for-each select="following-sibling::item[(position() + $currentPosition) <= $lastGroup]">
<item>
<position><xsl:value-of select="number(position/text()) - $currentPosition + 1"/></position>
<label><xsl:value-of select="label/text()"/></label>
</item>
</xsl:for-each>
</group>
</xsl:template>
<xsl:template match="item[not(marker)]">
<item>
<position><xsl:value-of select="position/text()"/></position>
<label><xsl:value-of select="label/text()"/></label>
</item>
</xsl:template>
</xsl:stylesheet>
I. XSLT 1.0 Solution:
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kFollowing"
match="item[not(marker[. = 'start_group'])
and
preceding-sibling::*[marker][1]/marker = 'start_group'
]"
use="generate-id(preceding-sibling::*
[marker[. = 'start_group']]
[1])"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item[marker[. = 'start_group']]">
<group position="{1 +count(preceding-sibling::*[. = 'start_group'])}"
id="{marker/#id}">
<xsl:copy-of select=".|key('kFollowing', generate-id())"/>
</group>
</xsl:template>
<xsl:template match=
"item[not(marker[. = 'start_group'])
and
preceding-sibling::*[marker][1]/marker = 'start_group'
]"/>
</xsl:stylesheet>
when applied on the provided XML document:
<root>
<item>
<position>1</position>
<label>Whatever1</label>
</item>
<item>
<position>2</position>
<label>Whatever2</label>
</item>
<item>
<position>3</position>
<label>Whatever3</label>
<marker id="unique1">start_group</marker>
</item>
<item>
<position>4</position>
<label>Whatever4</label>
</item>
<item>
<position>5</position>
<label>Whatever5</label>
</item>
<item>
<position>6</position>
<label>Whatever6</label>
<marker>last_in_group</marker>
</item>
<item>
<position>7</position>
<label>Whatever7</label>
<marker id="unique2">start_group</marker>
</item>
<item>
<position>8</position>
<label>Whatever8</label>
<marker>last_in_group</marker>
</item>
<item>
<position>9</position>
<label>Whatever9</label>
</item>
</root>
produces the wanted, correct result:
<root>
<item>
<position>1</position>
<label>Whatever1</label>
</item>
<item>
<position>2</position>
<label>Whatever2</label>
</item>
<group position="1" id="unique1">
<item>
<position>3</position>
<label>Whatever3</label>
<marker id="unique1">start_group</marker>
</item>
<item>
<position>4</position>
<label>Whatever4</label>
</item>
<item>
<position>5</position>
<label>Whatever5</label>
</item>
<item>
<position>6</position>
<label>Whatever6</label>
<marker>last_in_group</marker>
</item>
</group>
<group position="1" id="unique2">
<item>
<position>7</position>
<label>Whatever7</label>
<marker id="unique2">start_group</marker>
</item>
<item>
<position>8</position>
<label>Whatever8</label>
<marker>last_in_group</marker>
</item>
</group>
<item>
<position>9</position>
<label>Whatever9</label>
</item>
</root>
II. XSLT 2.0 solution:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<root>
<xsl:for-each-group select="item" group-starting-with=
"*[marker eq 'start_group'
or
not(marker)
and
preceding-sibling::*[marker][1]/marker eq 'last_in_group'
]
">
<xsl:choose>
<xsl:when test="current-group()[1]/marker">
<group position=
"{1 +count(current-group()[1]
/preceding-sibling::*
[marker = 'start_group'])}"
id="{marker/#id}">
<xsl:apply-templates select="current-group()"/>
</group>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</root>
</xsl:template>
</xsl:stylesheet>
When this XSLT 2.0 transformation is applied on the same XML document (above), the same correct result is produced.

Split XML file into multiple files based on a threshold value

I need to split the following XML file based on a predetermined value, for this example, lets assume I want to limit the "Item" node to three (3) within each file created.
Here's a sample input XML file:
<Items>
<Item>
<Title>Title 1</Title>
<DueDate>01-02-2008</DueDate>
</Item>
<Item>
<Title>Title 2</Title>
<DueDate>01-02-2009</DueDate>
</Item>
<Item>
<Title>Title 3</Title>
<DueDate>01-02-2010</DueDate>
</Item>
<Item>
<Title>Title 4</Title>
<DueDate>01-02-2011</DueDate>
</Item>
<Item>
<Title>Title 5</Title>
<DueDate>01-02-2012</DueDate>
</Item>
<Item>
<Title>Title 6</Title>
<DueDate>01-02-2013</DueDate>
</Item>
<Item>
<Title>Title 7</Title>
<DueDate>01-02-2013</DueDate>
</Item>
</Items>
The desired output based on the threshold value of 3, would be three files, two of which contain 3 "Item", and the last one containing the remaining "items", which would be one.
Here's a sample of my XSLT which does allow me to split them for each item, which results into seven separate files, however, what I desire is to limit the size of the file based on a certain limit of "Item" node per file.
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="xml" indent="yes" name="xml" />
<xsl:template match="/">
<xsl:for-each select="//Item">
<xsl:variable name="nTitle" select="Title"/>
<xsl:variable name="filename" select="concat('Items\',$nTitle,'-','.xml')" />
<xsl:value-of select="$filename" />
<xsl:result-document href="{$filename}" format="xml">
<xsl:copy-of select="."/>
</xsl:result-document>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This stylesheet:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:param name="pItemsNumber" select="3"/>
<xsl:template match="Items">
<xsl:for-each-group select="Item"
group-adjacent="(position()-1) idiv $pItemsNumber">
<xsl:result-document href="Items\{current-grouping-key()}.xml">
<Items>
<xsl:copy-of select="current-group()"/>
</Items>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<Items>
<Item>
<Title>Title 1</Title>
<DueDate>01-02-2008</DueDate>
</Item>
<Item>
<Title>Title 2</Title>
<DueDate>01-02-2009</DueDate>
</Item>
<Item>
<Title>Title 3</Title>
<DueDate>01-02-2010</DueDate>
</Item>
</Items>
<?xml version="1.0" encoding="UTF-8"?>
<Items>
<Item>
<Title>Title 4</Title>
<DueDate>01-02-2011</DueDate>
</Item>
<Item>
<Title>Title 5</Title>
<DueDate>01-02-2012</DueDate>
</Item>
<Item>
<Title>Title 6</Title>
<DueDate>01-02-2013</DueDate>
</Item>
</Items>
<?xml version="1.0" encoding="UTF-8"?>
<Items>
<Item>
<Title>Title 7</Title>
<DueDate>01-02-2013</DueDate>
</Item>
</Items>
Edit: Oops!
This transformation:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pSplitNum" select="3"/>
<xsl:template match="node()|#*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Item[position() mod $pSplitNum eq 1]">
<xsl:result-document href=
"file{position()}-{min((position()+$pSplitNum -1, count(/*/Item)))}.xml">
<Items>
<xsl:call-template name="identity"/>
<xsl:apply-templates mode="copy" select=
"following-sibling::Item[position() lt $pSplitNum]"/>
</Items>
</xsl:result-document>
</xsl:template>
<xsl:template match="/*"><xsl:apply-templates/></xsl:template>
<xsl:template match="Item[position() mod $pSplitNum ne 1]"/>
</xsl:stylesheet>
when applied on the provided XML document:
<Items>
<Item>
<Title>Title 1</Title>
<DueDate>01-02-2008</DueDate>
</Item>
<Item>
<Title>Title 2</Title>
<DueDate>01-02-2009</DueDate>
</Item>
<Item>
<Title>Title 3</Title>
<DueDate>01-02-2010</DueDate>
</Item>
<Item>
<Title>Title 4</Title>
<DueDate>01-02-2011</DueDate>
</Item>
<Item>
<Title>Title 5</Title>
<DueDate>01-02-2012</DueDate>
</Item>
<Item>
<Title>Title 6</Title>
<DueDate>01-02-2013</DueDate>
</Item>
<Item>
<Title>Title 7</Title>
<DueDate>01-02-2013</DueDate>
</Item>
</Items>
produces the wanted three xml files:
Saxon 9.1.0.5J from Saxonica
Java version 1.6.0_22
Stylesheet compilation time: 645 milliseconds
Processing file:/C:/Program%20Files/Java/jre6/bin/marrowtr.xml
Building tree for file:/C:/Program%20Files/Java/jre6/bin/marrowtr.xml using class net.sf.saxon.tinytree.TinyBuilder
Tree built in 10 milliseconds
Tree size: 38 nodes, 119 characters, 0 attributes
Loading net.sf.saxon.event.MessageEmitter
Writing to file:/C:/Program%20Files/Java/jre6/bin/file1-3.xml
Writing to file:/C:/Program%20Files/Java/jre6/bin/file4-6.xml
Writing to file:/C:/Program%20Files/Java/jre6/bin/file7-7.xml
Execution time: 101 milliseconds
Memory used: 11453088
NamePool contents: 20 entries in 20 chains. 6 prefixes, 7 URIs
Do note:
This is a simple application of the identity rule pattern.
Every Item starting a new file is matched and it causes the wrapping in a top element, processing of itself and the next $pSplitNum -1 (or whatever remains in the last group), and outputting this as a single result-document (file).
The name of every file created is: "filex-y.xml", where x and y are the starting and ending indexes of the Item elements written in the file.
Every Item that isn't starting a new file is deleted by an empty matching template. Such elements are processed in "copy" mode.
You could implement a counter that is declared outside of your loop. When the counter hits 3, reset it and set a new filename. Otherwise, increment and append to the existing filename.