malenkiy_scot
malenkiy_scot

Reputation: 16605

Removing and copying XML elements with XSLT

With XSLT, I'd like to transform an XML file that has the following structure:

<e1>
  <e2 a="a1" b="b1" c="c1">
    <e3 foo="a"/>
    <e3 foo="b"/>
    <e3 foo="c"/>
    ...
  </e2>
  <e2 a="a2" b="b2" c="c2">
    <e3 foo="d"/>
    ...
  </e2>
  ...
</e1>

Into:

<e1>
  <e2 a="a1" b="b1" c="c1">
    <e3 a="a1" b="b1" e="e"/>
  </e2>
  <e2 a="a2" b="b2" c="c2">
    <e3 a="a2" b="b2" e="e"/>
  </e2>
  ...
</e1>

In words: I need to remove e3 elements completely, and substitute them with a copy of the enclosing e2 element, with its name changed to e3; copying some of the attributes (e.g. a, b) to the new element, and adding some new attributes (e.g. e).

Anything else must stay intact.

Thank you in advance.

Upvotes: 0

Views: 111

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116959

Perhaps this can work for you:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<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="e2[e3]">   
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
        <e3 a="{@a}" b="{@b}" e="e"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="e3"/>

</xsl:stylesheet>

It removes all existing e3 elements and - for any e2 element that contains at least one e3 child element - adds a new e3 element, copying the @a and @b attributes from the parent e2 and adding a new @e attribute. Everything else is copied as is.

Upvotes: 3

Related Questions