Add element between two other elements via XSLT?

I have the following input XML:

<root>
    <aaa>some string aaa</aaa>
    <bbb>some string bbb</bbb>
    <ddd>some string ddd</ddd> 
</root>

Using XSLT I want to the following output:

<root>
    <aaa>some string aaa</aaa>
    <bbb>some string bbb</bbb>
    <ccc>some string ccc</ccc>
    <ddd>some string ddd</ddd>
</root>

My XSLT is:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.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="root">
        <root>
            <ccc>some string ccc</ccc>
            <xsl:apply-templates select="@*|node()"/> 
        </root>
    </xsl:template>
</xsl:stylesheet>

But I'm not getting my desired output. How could I put the ccc element between bbb and ddd elements using the identity template?

I can use XSLT 3.0 if that helps.

Upvotes: 3

Views: 3828

Answers (2)

Martin Honnen
Martin Honnen

Reputation: 167471

Kenneth's answer is fine but as the question is tagged as XSLT 3.0 it can be written more compact so I add this answer as an alternative

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="3.0">

    <xsl:output indent="yes"/>

    <xsl:mode on-no-match="shallow-copy"/>

    <xsl:template match="ddd">
        <ccc>some string ccc</ccc>
        <xsl:next-match/>
    </xsl:template>

</xsl:stylesheet>

using <xsl:mode on-no-match="shallow-copy"/> to express the identity transformation and using <xsl:next-match/> to delegate copying of the ddd element to it.

Upvotes: 3

kjhughes
kjhughes

Reputation: 111511

Use the identity transformation with a second template that matches the element before or after the insertion point, and then insert the new element after or before copying over the matched element. To wit:

Given this input XML,

<root>
   <aaa>some string aaa</aaa>
   <bbb>some string bbb</bbb>
   <ddd>some string ddd</ddd> 
</root>

this XSLT,

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:output method="xml" indent="yes"/>

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

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

</xsl:stylesheet>

will generate this output XML:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <aaa>some string aaa</aaa>
   <bbb>some string bbb</bbb>
   <ccc>some string ccc</ccc>
   <ddd>some string ddd</ddd> 
</root>

Upvotes: 3

Related Questions