We will detail how we can move an XML element into another element using XSLT.

Input

Following is the example input that we will work with. We will move topic element into chapter element.

<book>
  <chapter topic="animalsTopic"/>
  <topic name="animalsTopic">
    <title>Animals</title>
    <content>Dog is an animal.</content>
  </topic>
</book>

Transformation

Here is XSLT that performs the move operation. It includes 3 templates.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="chapter">
    <xsl:copy>
      <xsl:copy-of select="following-sibling::topic[@name='animalsTopic']"/>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="topic[@name='animalsTopic']"/>

</xsl:stylesheet>

 

First template is the identity template. It copies all given input to the output without modification. Other two templates override this default behavior to perform move operation.

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

 

Second template matches chapter element  and adds topic element into it. Then it copies all child nodes of chapter using <xsl:apply-templates/>. Note that attributes are not part of this copy operation.

<xsl:template match="chapter">
  <xsl:copy>
    <xsl:copy-of select="following-sibling::topic[@name='animalsTopic']"/>
    <xsl:apply-templates/>
  </xsl:copy>
</xsl:template>

 

Third template matches the topic element and does nothing. As a result, this will discard the element from resulting XML. This ensures that we will not have duplicate topic elements after the move operation.

<xsl:template match="topic[@name='animalsTopic']"/>

 

Output is as follows. Topic element is nested in chapter element.

<book>
  <chapter>
      <topic name="animalsTopic">
         <title>Animals</title>
         <content>Dog is an animal.</content>
      </topic>
   </chapter>
  
</book>

 

Enhancement

Above output includes a blank line before </book> tag. This is created by built-in XSLT templates. To disable creation of these blank lines, we should override default behavior. Following template will override generation of blank lines.

<xsl:template match="text()"/>