'Move the selected nodes to different node and remove selected elements

I'm trying to move the nodes and remove the array element fields. In the below XML there are multiple occurences of phoneVoice and Addresses field, iam trying to make these elements as root and inside node as array. Below is the request xml

<rsp:response xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rsp="rsp.com/employee/Response/v30"
xmlns:res="res.com/Member/details/v1"
xmlns:resp="resp.com/details/v1">
<res:employee>
    <resp:Employee>
        <resp:FirstName>abc</resp:FirstName>
        <resp:middleName></resp:middleName>
        <resp:details>
            <resp:Details>
                <resp:type>postal</resp:type>  
                <resp:phonesVoice>
                    <resp:Phone>
                        <resp:textLabel>LIFELINE</resp:textLabel>
                        <resp:number/>
                    </resp:Phone>
                </resp:phonesVoice>
                <resp:phonesVoice>
                    <resp:Phone>
                        <resp:textLabel>Intl</resp:textLabel>
                        <resp:number/>
                    </resp:Phone>
                </resp:phonesVoice>
                <resp:Addresses>
                    <resp:Address>
                        <resp:country>XYZ</resp:country>
                    </resp:Address>
                </resp:Addresses>
            </resp:Details>
            <resp:Details>
                <resp:type>ofc</resp:type> 
                <resp:Addresses>
                    <resp:Address>
                        <resp:country>XYZ</resp:country>
                    </resp:Address>
                </resp:Addresses>
            </resp:Details>
        </resp:details>
    </resp:Employee>
</res:employee>

</rsp:response>

Below is the XSLT used to achieve the result.

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:resp="resp.com/details/v1">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="resp:details">
    <xsl:copy>
        <Details>
            <xsl:apply-templates select="@*|resp:Details/*"/>
        </Details>
    </xsl:copy>
</xsl:template>


<xsl:template match="resp:Address">
    <xsl:copy>
        <xsl:apply-templates/>
        <xsl:copy-of select="../../resp:type"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="resp:type"/>

</xsl:stylesheet>

Below is the output of the XSLT(partially achieved)

    <?xml version="1.0" encoding="UTF-8"?>
<rsp:response xmlns:xs="http://www.w3.org/2001/XMLSchema"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns:rsp="rsp.com/employee/Response/v30"
              xmlns:res="res.com/Member/details/v1"
              xmlns:resp="resp.com/details/v1">
   <res:employee>
      <resp:Employee>
         <resp:FirstName>abc</resp:FirstName>
         <resp:middleName/>
         <resp:details>
            <Details>
               <resp:phonesVoice>
                  <resp:Phone>
                     <resp:textLabel>LIFELINE</resp:textLabel>
                     <resp:number/>
                  </resp:Phone>
               </resp:phonesVoice>
               <resp:phonesVoice>
                  <resp:Phone>
                     <resp:textLabel>Intl</resp:textLabel>
                     <resp:number/>
                  </resp:Phone>
               </resp:phonesVoice>
               <resp:Addresses>
                  <resp:Address>
                     <resp:country>XYZ</resp:country>
                     <resp:type>postal</resp:type>
                  </resp:Address>
               </resp:Addresses>
               <resp:Addresses>
                  <resp:Address>
                     <resp:country>XYZ</resp:country>
                     <resp:type>ofc</resp:type>
                  </resp:Address>
               </resp:Addresses>
            </Details>
         </resp:details>
      </resp:Employee>
   </res:employee>
</rsp:response>

Below is the desired output

    <?xml version="1.0" encoding="UTF-8"?>
<rsp:response xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:rsp="rsp.com/employee/Response/v30"
    xmlns:res="res.com/Member/details/v1"
    xmlns:resp="resp.com/details/v1">
    <res:employee>
        <resp:Employee>
            <resp:FirstName>abc</resp:FirstName>
            <resp:middleName/>
            <resp:details>
                <Details>
                    <resp:phonesVoice>
                        <resp:Phone>
                            <resp:textLabel>LIFELINE</resp:textLabel>
                            <resp:number/>
                        </resp:Phone>
                        <resp:Phone>
                            <resp:textLabel>Intl</resp:textLabel>
                            <resp:number/>
                        </resp:Phone>
                    </resp:phonesVoice>
                    <resp:Addresses>
                        <resp:Address>
                            <resp:country>XYZ</resp:country>
                            <resp:type>postal</resp:type>
                        </resp:Address>
                        <resp:Address>
                            <resp:country>XYZ</resp:country>
                            <resp:type>ofc</resp:type>
                        </resp:Address>
                    </resp:Addresses>
                </Details>
            </resp:details>
        </resp:Employee>
    </res:employee>
</rsp:response>


Solution 1:[1]

AFAICT you want to do:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:resp="resp.com/details/v1">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="resp:details">
    <xsl:variable name="phones" select="resp:Details/resp:phonesVoice" />
    <xsl:variable name="addr" select="resp:Details/resp:Addresses" />
    <xsl:copy>
        <Details>
            <xsl:if test="$phones">
                <resp:phonesVoice>
                    <xsl:copy-of select="$phones/resp:Phone"/>
                </resp:phonesVoice>
            </xsl:if>
            <xsl:if test="$addr">
                <resp:Addresses>
                    <xsl:apply-templates select="$addr/resp:Address"/>
                </resp:Addresses>
            </xsl:if>
        </Details>
    </xsl:copy>    
</xsl:template>

<xsl:template match="resp:Address">
    <xsl:copy>
        <xsl:copy-of select="resp:country"/>
        <xsl:copy-of select="../../resp:type"/>
    </xsl:copy>    
</xsl:template>

</xsl:stylesheet> 

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1