I have a requirement ,as below, in XSLT
A sample xml input replicating my actual scenario.
<Root>
<List1>
<list1Child>
<Id>1</Id>
<Name>Test1</Name>
</list1Child>
<list1Child>
<Id>2</Id>
<Name>Test2</Name>
</list1Child>
</List1>
<List2>
<list2Child>
<AoId>1</AoId>
<Department>Dep1</Department>
</list2Child>
<list2Child>
<AoId>1</AoId>
<Department>Dep11</Department>
</list2Child>
<list2Child>
<AoId>2</AoId>
<Department>Dep2</Department>
</list2Child>
</List2>
</Root>
Here, I would want the List2 elements to appear as nested elements under list 1.Here Id and AoId are matching keys
Sample output below
<Root>
<List1>
<list1Child>
<Id>1</Id>
<Name>Test1</Name>
<List2>
<list2Child>
<AoId>1</AoId>
<Department>Dep1</Department>
</list2Child>
<list2Child>
<AoId>1</AoId>
<Department>Dep11</Department>
</list2Child>
</List2>
</list1Child>
<list1Child>
<Id>2</Id>
<Name>Test2</Name>
<List2>
<list2Child>
<AoId>2</AoId>
<Department>Dep2</Department>
</list2Child>
</List2>
</list1Child>
</List1>
</Root>
I am using XSLT (version 2) and was able to do this with nested for-each loop and predicates. Snippet of the pseudocode provided below
<xsl:stylesheet version="2.0">
<xsl:template match="/">
<xsl:for-each select="/Root/List1/list1Child">
..
..
..
<xsl:for-each select="/Root/List2/list2Child [AoId=Id]">
..
..
..
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
However, in certain cases, I have a very large xml and this xslt takes around 10 seconds. I would want to improve performance. I thought using keys might improve the performance and tried the below
<xsl:stylesheet version="2.0">
<xsl:key name="List2Key" match="list2Child" use="AoId"/>
<xsl:template match="/">
<xsl:for-each select="/Root/List1/list1Child">
..
..
..
<xsl:for-each select="key(‘List2Key’,Id)">
..
..
..
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
However the above fails to get parsed. Maybe the key is of a different node and is probably not getting recognized under the first for-each node? I tried to use for-each-group
and Muenchian Method. However couldn’t get that to work.Is there any other more efficient way to achieve this nested structure. Appreciate any directions for the effective solution.
6
I wasn’t able to reproduce the problem you report with the key. I believe I am getting the expected result using:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="List2Key" match="list2Child" use="AoId"/>
<xsl:template match="/Root">
<xsl:copy>
<List1>
<xsl:for-each select="List1/list1Child">
<xsl:copy>
<xsl:copy-of select="*"/>
<List2>
<xsl:copy-of select="key('List2Key', Id)"/>
</List2>
</xsl:copy>
</xsl:for-each>
</List1>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Whether it’s more efficient or not depends on the processor being used.
8