Reputation: 1754
I have an XML that looks like this:
<request>
<MaterialOrderItems>
<Item>
<LineId>1</LineId>
<ParentLineId>1</ParentLineId>
</Item>
<Item>
<LineId>2</LineId>
<ParentLineId>1</ParentLineId>
</Item>
<Item>
<LineId>3</LineId>
<ParentLineId>1</ParentLineId>
</Item>
</MaterialOrderItems>
</request>
I want to take this XML, and duplicate this Item group (Item[1,2,3]) into multiple copies. For example, if I want 2 copies, my final xml will look like this:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<request>
<MaterialOrderItems>
<Item>
<LineId>1</LineId>
<ParentLineId>1</ParentLineId>
</Item>
<Item>
<LineId>2</LineId>
<ParentLineId>1</ParentLineId>
</Item>
<Item>
<LineId>3</LineId>
<ParentLineId>1</ParentLineId>
</Item>
<Item>
<LineId>4</LineId>
<ParentLineId>4</ParentLineId>
</Item>
<Item>
<LineId>5</LineId>
<ParentLineId>4</ParentLineId>
</Item>
<Item>
<LineId>6</LineId>
<ParentLineId>4</ParentLineId>
</Item>
</MaterialOrderItems>
</request>
I have come up with this xslt to do this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml" version="1.0">
<xsl:output encoding="UTF-8" indent="yes" method="xml" standalone="no"
omit-xml-declaration="no"/>
<xsl:param name="nmaterials" select="2" />
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//MaterialOrderItems" name="order">
<xsl:param name="material_number" select="1" />
<xsl:copy>
<Item>
<LineId><xsl:value-of select="((($material_number - 1) * 3) + 1)"/></LineId>
<ParentLineId><xsl:value-of select="((($material_number - 1) * 3) + 1)"/></ParentLineId>
</Item>
<Item>
<LineId><xsl:value-of select="((($material_number - 1) * 3) + 2)"/></LineId>
<ParentLineId><xsl:value-of select="((($material_number - 1) * 3) + 1)"/></ParentLineId>
</Item>
<Item>
<LineId><xsl:value-of select="((($material_number - 1) * 3) + 3)"/></LineId>
<ParentLineId><xsl:value-of select="((($material_number - 1) * 3) + 1)"/></ParentLineId>
</Item>
</xsl:copy>
<xsl:if test="$material_number < $nmaterials">
<xsl:apply-templates select=".">
<xsl:with-param name="material_number" select="$material_number + 1" />
</xsl:apply-templates>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
and am getting this output:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<request>
<MaterialOrderItems>
<Item>
<LineId>1</LineId>
<ParentLineId>1</ParentLineId>
</Item>
<Item>
<LineId>2</LineId>
<ParentLineId>1</ParentLineId>
</Item>
<Item>
<LineId>3</LineId>
<ParentLineId>1</ParentLineId>
</Item>
</MaterialOrderItems>
<MaterialOrderItems>
<Item>
<LineId>4</LineId>
<ParentLineId>4</ParentLineId>
</Item>
<Item>
<LineId>5</LineId>
<ParentLineId>4</ParentLineId>
</Item>
<Item>
<LineId>6</LineId>
<ParentLineId>4</ParentLineId>
</Item>
</MaterialOrderItems>
</request>
I have two questions:
Please help.
Upvotes: 0
Views: 113
Reputation: 3445
Try below code
see transformation at https://xsltfiddle.liberty-development.net/3NSTbeS
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:param name="nmaterials" select="2"/>
<xsl:template match="MaterialOrderItems">
<xsl:param name="material_number" select="1"/>
<xsl:variable name="countitem" select="count(Item)"/>
<xsl:copy>
<xsl:copy-of select="*"/>
<xsl:if test="$material_number != $nmaterials">
<xsl:call-template name="Copy">
<xsl:with-param name="data" select="."/>
<xsl:with-param name="material_number" select="$material_number + 1"/>
<xsl:with-param name="countitem" select="$countitem"/>
</xsl:call-template>
</xsl:if>
</xsl:copy>
</xsl:template>
<xsl:template name="Copy">
<xsl:param name="data"/>
<xsl:param name="material_number"/>
<xsl:param name="countitem"/>
<xsl:for-each select="$data/Item">
<xsl:variable name="position" select="position()"/>
<xsl:apply-templates select=".">
<xsl:with-param name="pos" select="$position"/>
<xsl:with-param name="material_number" select="$material_number"/>
<xsl:with-param name="countitem" select="$countitem"/>
</xsl:apply-templates>
</xsl:for-each>
<xsl:if test="$material_number != $nmaterials">
<xsl:call-template name="Copy">
<xsl:with-param name="data" select="$data"/>
<xsl:with-param name="material_number" select="$material_number + 1"/>
<xsl:with-param name="countitem" select="$countitem"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="Item">
<xsl:param name="pos"/>
<xsl:param name="material_number"/>
<xsl:param name="countitem"/>
<xsl:copy>
<LineId>
<xsl:value-of select="((($material_number - 1) * $countitem) + $pos)"/>
</LineId>
<ParentLineId>
<xsl:value-of select="((($material_number - 1) * $countitem) + 1)"/>
</ParentLineId>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Upvotes: 1