XML merge nodes with XSLT -


i have xml file that:

<root>  <scenario name="film1">   <case name="aaa">     <test name="test1">ok</test>   </case>   <case name="bbb">     <test name="test2">not ok</test>   </case>   <case name="aaa">     <test name="test3">not ok</test>   </case>   <case name="bbb">     <test name="test66">ok</test>   </case>  </scenario> </root> 

of course there more nodes scenario want group case each scenario. expect that:

<root>  <scenario name="fil1">   <case name="aaa">     <test name="test1">ok</test>     <test name="test3">not ok</test>   </case>    <case name="bbb">     <test name="test2">not ok</test>     <test name="test66">ok</test>   </case>  </scenario> </root> 

i made xslt file:

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"     xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">     <xsl:output method="xml" indent="yes"/>     <xsl:template match="root">         <xsl:copy>             <xsl:apply-templates/>         </xsl:copy>     </xsl:template>   <xsl:template match="scenario">     <scenario>       <xsl:attribute name="name">         <xsl:value-of select="@name"/>       </xsl:attribute>       <xsl:apply-templates/>     </scenario>   </xsl:template>   <xsl:template match ="case">     <case>       <xsl:attribute name="name">         <xsl:value-of select="@name"/>       </xsl:attribute>     </case>   </xsl:template> </xsl:stylesheet> 

do know should now?

you in question want group case each scenario. if have multiple scenario elements, , want group case elements within each such element, need make use of concatenated key:

<xsl:key name="case" match="case" use="concat(../@name, '|', @name)" /> 

this means if had 2 case elements same name, in different scenario elements, still grouped separately.

now, grouping, each case statement within scenario, need find case elements occur first in key given attributes. can done follows:

<xsl:apply-templates select="case[generate-id() = generate-id(key('case', concat(../@name, '|', @name))[1])]" /> 

to break down...

key('case', concat(../@name, '|', @name)) - gets elements same attributes

key('case', concat(../@name, '|', @name))[1] - gets first element of list

generate-id(key('case', concat(../@name, '|', @name))[1]) - generates unique id first element, can compared current element.

so, effectively, distinct elements. can items in "group" using key again

<xsl:for-each select="key('case', concat(../@name, '|', @name))"> 

try xslt

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform">     <xsl:key name="case" match="case" use="concat(../@name, '|', @name)" />     <xsl:output method="xml" indent="yes"/>      <xsl:template match="@*|node()">         <xsl:copy>             <xsl:apply-templates select="@*|node()" />         </xsl:copy>     </xsl:template>      <xsl:template match="scenario">         <xsl:copy>             <xsl:apply-templates select="@*" />             <xsl:apply-templates select="case[generate-id() = generate-id(key('case', concat(../@name, '|', @name))[1])]" />         </xsl:copy>     </xsl:template>      <xsl:template match ="case">         <xsl:copy>             <xsl:apply-templates select="@*" />             <xsl:for-each select="key('case', concat(../@name, '|', @name))">                 <xsl:apply-templates />             </xsl:for-each>         </xsl:copy>     </xsl:template> </xsl:stylesheet> 

as mentioned in comments, definitive article on approach can found @ http://www.jenitennison.com/xslt/grouping/muenchian.html, worth reading it, , re-reading it, practising it, until understand it.

also, note use of identity transform, means don't have write template each specific element if want copy without changes.


Comments

Popular posts from this blog

toolbar - How to add link to user registration inside toobar in admin joomla 3 custom component -

linux - disk space limitation when creating war file -

How to provide Authorization & Authentication using Asp.net, C#? -