xml - Merge all child nodes of respective parent under first parent, if parent node value matches -


hi input this.

<?xml version="1.0" encoding="utf-8"?>          <claim>             <mileage>9837</mileage>             <damageposition>                <damageseqnumber>3</damageseqnumber>                <damagecode>2727004</damagecode>                <partposition>                   <seqnumber>1</seqnumber>                   <partnumber>a2035400253</partnumber>                </partposition>             </damageposition>             <damageposition>                <damageseqnumber>1</damageseqnumber>                <damagecode>2727004</damagecode>                <partposition>                   <seqnumber>3</seqnumber>                   <partnumber>a1409910055</partnumber>                </partposition>             </damageposition>             <damageposition>                <damageseqnumber>8</damageseqnumber>                <damagecode>2727004</damagecode>                <operationposition>                   <seqnumber>8</seqnumber>                   <opcode>02-2710-01</opcode>                </operationposition>             </damageposition>             <damageposition>                <damageseqnumber>4</damageseqnumber>                <damagecode>3221136</damagecode>                <partposition>                   <seqnumber>4</seqnumber>                   <partnumber>a2033202889</partnumber>                </partposition>             </damageposition>          </claim>   

and desired output :

<?xml version="1.0" encoding="utf-8"?>          <claim>             <mileage>9837</mileage>             <damageposition>                <damageseqnumber>3</damageseqnumber>                <damagecode>2727004</damagecode>                <operationposition>                   <seqnumber>8</seqnumber>                   <opcode>02-2710-01</opcode>                </operationposition>                <partposition>                   <seqnumber>1</seqnumber>                   <partnumber>a2035400253</partnumber>                </partposition>                <partposition>                   <seqnumber>3</seqnumber>                   <partnumber>a1409910055</partnumber>                </partposition>                <operationposition>                   <seqnumber>8</seqnumber>                   <opcode>02-2710-01</opcode>                </operationposition>             </damageposition>             <damageposition>                <damageseqnumber>4</damageseqnumber>                <damagecode>3221136</damagecode>                <partposition>                   <seqnumber>4</seqnumber>                   <partnumber>a2033202889</partnumber>                </partposition>             </damageposition>          </claim> 

i tried following xslt:

<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="kuserid" match="damageposition"  use="damagecode"/>  <xsl:template match="node()|@*">      <xsl:copy>        <xsl:apply-templates select="node()|@*">          <xsl:sort select="damagecode" data-type="number"/>        </xsl:apply-templates>      </xsl:copy>  </xsl:template>  <xsl:template match=  "damageposition|damagecode  |partposition"/>  <xsl:template match=   "damageposition     [generate-id()     =      generate-id(key('kuserid', damagecode)[1])      ]">   <damageposition>    <xsl:copy-of select="damagecode"/>    <xsl:apply-templates mode="copy" select="key('kuserid',damagecode)" />   </damageposition>  </xsl:template>  <xsl:template match="damageposition" mode="copy">   <partposition>    <xsl:apply-templates/>   </partposition>  </xsl:template> </xsl:stylesheet> 

and giving me ouput below, though able group child elements having same damagecode, not giving desired ouput, not copying tags under part position, seqnumber visible in output . appreciated. help.

<claim>    <mileage>9837</mileage>    <damageposition>       <damagecode>2727004</damagecode>       <partposition>          <damageseqnumber>3</damageseqnumber>       </partposition>       <partposition>          <damageseqnumber>1</damageseqnumber>       </partposition>       <partposition>          <damageseqnumber>8</damageseqnumber>          <operationposition>             <seqnumber>8</seqnumber>             <opcode>02-2710-01</opcode>          </operationposition>       </partposition>    </damageposition>    <damageposition>       <damagecode>3221136</damagecode>       <partposition>          <damageseqnumber>4</damageseqnumber>       </partposition>    </damageposition> </claim> 

you have template in xslt ignores partposition

<xsl:template match="damageposition|damagecode|partposition"/> 

therefore, when <xsl:apply-templates/> in copy template, because positioned on damageposition @ point, above template match child partposition , ignore it.

perhaps should ignoring damageseqnumber instead of partposition @ point?

also, don't need copy template @ all. instead, change call it, child elements of key, , let identity template take care of it.

<xsl:apply-templates select="key('kuserid',damagecode)/*" /> 

try xslt

<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="kuserid" match="damageposition"  use="damagecode"/>   <xsl:template match="node()|@*">      <xsl:copy>        <xsl:apply-templates select="node()|@*">          <xsl:sort select="damagecode" data-type="number"/>        </xsl:apply-templates>      </xsl:copy>  </xsl:template>   <xsl:template match="damageposition|damagecode|damageseqnumber"/>   <xsl:template match="damageposition[generate-id() = generate-id(key('kuserid', damagecode)[1])]">   <damageposition>    <xsl:copy-of select="damagecode"/>    <xsl:copy-of select="damageseqnumber"/>    <xsl:apply-templates select="key('kuserid',damagecode)/*" />   </damageposition>  </xsl:template> </xsl:stylesheet> 

this doesn't quite give output show in question, because show 2 operationposition elements in output, although there 1 in input.

edit: if wanted operationposition elements before partposition elements, replace existing <xsl:apply-templates select="key('kuserid',damagecode)/*" /> these 2 lines instead:

<xsl:apply-templates select="key('kuserid',damagecode)/operationposition" /> <xsl:apply-templates select="key('kuserid',damagecode)/*[not(self::operationposition)]" /> 

Comments