I have to transform an xml message that looks like similar to below. The source content of each node is effectively the same, with a different node name (parentitem, childitem, subchild).
I have inherited an XSLT that addresses the solution by hardcoding each case with little template use, which has significant duplicated XSLT.
I would like to know what options I have to optimise the XSLT to reduce duplicate of XSLT.
I tried to use setup a single template for a generic "node"; then tried to use call-template; However I wasn't able to figure out how to nest objects within the generic
Any help appreciated, Thank you.
<item>
<itemdetail>
<parentitem>
<item>001</item>
<code1>1</code1>
<code2>2</code2>
<itemattribute>
<item_desc>ParentItem</item_desc>
</itemattribute>
</parentitem>
<childitem>
<item>002</item>
<code1>2</code1>
<code2>2</code2>
<itemattribute>
<item_desc>ChildItemLevel1</item_desc>
</itemattribute>
</childitem>
<subchildren>
<subchild>
<item>003</item>
<code1>2</code1>
<code2>1</code2>
<itemattribute>
<item_desc>SubChild003</item_desc>
</itemattribute>
</subchild>
<subchild>
<item>004</item>
<code1>2</code1>
<code2>1</code2>
<itemattribute>
<item_desc>SubChild004</item_desc>
</itemattribute>
</subchild>
</subchildren>
</itemdetail>
</item>
There are a few variations of the message The required transformation is required to look similar to below.
- Parent and Child will only have 0 or 1 instances
- Child is nested under the Parent
- SubChild(ren) are nested under the Child
Case | parentitem Node | ChildItem Present | SubChildren Present |
---|---|---|---|
Case 1 | Y | Y | Y |
Case 2 | Y | N | N |
Case 3 | Y | Y | N |
Case 4 | N | Y | N |
Case 5 | N | Y | Y |
Case 6 | N | N | Y |
Case 1
<Products>
<Product type="parentitem">
<item>001</item>
<code1>1</code1>
<code2>2</code2>
<itemattribute>
<item_desc>parentitem</item_desc>
</itemattribute>
<Product type="childitem">
<item>002</item>
<code1>2</code1>
<code2>2</code2>
<itemattribute>
<item_desc>childitem</item_desc>
</itemattribute>
<Product type="subchild">
<item>003</item>
<code1>2</code1>
<code2>1</code2>
<itemattribute>
<item_desc>SubChild003</item_desc>
</itemattribute>
</Product>
<Product type="subchild">
<item>004</item>
<code1>2</code1>
<code2>1</code2>
<itemattribute>
<item_desc>SubChild004</item_desc>
</itemattribute>
</Product>
</Product>
</Product>
</Products>
Case 2
<Products>
<Product type="parentitem">
<item>001</item>
<code1>1</code1>
<code2>2</code2>
<itemattribute>
<item_desc>parentitem</item_desc>
</itemattribute>
</Product>
</Products>
Case 3
<Products>
<Product type="parentitem">
<item>001</item>
<code1>1</code1>
<code2>2</code2>
<itemattribute>
<item_desc>parentitem</item_desc>
</itemattribute>
<Product type="childitem">
<item>002</item>
<code1>2</code1>
<code2>2</code2>
<itemattribute>
<item_desc>childitem</item_desc>
</itemattribute>
</Product>
</Product>
</Product>
</Products>
CodePudding user response:
Would something like this work for you? I believe it covers even more cases than the 6 you have elaborated.
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="itemdetail">
<Products>
<xsl:apply-templates select="parentitem"/>
<xsl:apply-templates select="childitem[not(../parentitem)]"/>
<xsl:apply-templates select="subchildren[not(../parentitem | ../childitem)]"/>
</Products>
</xsl:template>
<xsl:template match="parentitem">
<Product type="parentitem">
<xsl:copy-of select="*"/>
<xsl:apply-templates select="../childitem"/>
<xsl:apply-templates select="../subchildren[not(../childitem)]"/>
</Product>
</xsl:template>
<xsl:template match="childitem">
<Product type="childitem">
<xsl:copy-of select="*"/>
<xsl:apply-templates select="../subchildren"/>
</Product>
</xsl:template>
<xsl:template match="subchild">
<Product type="subchild">
<xsl:copy-of select="*"/>
</Product>
</xsl:template>
</xsl:stylesheet>