0

I have an XML file being sent to me from a third-party in the following format:

<Events>
  <COMPLETE>
    <TASK>1</TASK>
    <TIME>18:29</TIME>
    <USER>User1</USER>
    <DEP>OPPS</DEP>
  </COMPLETE>
  <PROGRESS>
    <TASK>2</TASK>
    <TIME>09:15</TIME>
    <USER>User1</USER>
    <DEP>OPPS</DEP>
  </PROGRESS>
  <PROGRESS>
    <TASK>2</TASK>
    <TIME>11:41</TIME>
    <USER>User2</USER>
    <DEP>COMS</DEP>
  </PROGRESS>
  <CLOSED>
    <TASK>3</TASK>
    <TIME>17:10</TIME>
    <DETAILS>
       <TIMECLOSED>17:01</TIMECLOSED>
       <CHECKEDBY>User9</CHECKEDBY>
    </DETAILS>
    <TAKEN>6.5</TAKEN>
    <USER>User8</USER>
    <DEP>FUNDS</DEP>
  </CLOSED>
  <COMPLETE>
    <TASK>4</TASK>
    <TIME>18:03</TIME>
    <USER>User3</USER>
    <DEP>COMS</DEP>
  </COMPLETE>
<Events>

Is there a way using XSLT to convert the child nodes of the Events element to be named Event and have an attribute called Name with the current child elements name. The output I was looking for is:

<Events>
  <Event Name='COMPLETE'>              <-- Changed
    <TASK>1</TASK>
    <TIME>18:29</TIME>
    <USER>User1</USER>
    <DEP>OPPS</DEP>
  </Event>
  <Event Name='PROGRESS'>              <-- Changed
    <TASK>2</TASK>
    <TIME>09:15</TIME>
    <USER>User1</USER>
    <DEP>OPPS</DEP>
  </Event>
  <Event Name='PROGRESS'>              <-- Changed
    <TASK>2</TASK>
    <TIME>11:41</TIME>
    <USER>User2</USER>
    <DEP>COMS</DEP>
  </PROGRESS>
  <Event Name='CLOSED'>                <-- Changed
    <TASK>3</TASK>
    <TIME>17:10</TIME>
    <DETAILS>
       <TIMECLOSED>17:01</TIMECLOSED>
       <CHECKEDBY>User9</CHECKEDBY>
    </DETAILS>
    <TAKEN>6.5</TAKEN>
    <USER>User8</USER>
    <DEP>FUNDS</DEP>
  </Event>
  <Event Name='COMPLETE'>              <-- Changed
    <TASK>4</TASK>
    <TIME>18:03</TIME>
    <USER>User3</USER>
    <DEP>COMS</DEP>
  </Event>
<Events>

I've looked online considerably and can not find how to do this. Many thanks!

Thomas Byrne
  • 127
  • 1
  • 2
  • 15

2 Answers2

1

As an addition to an identity stylesheet:

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

<xsl:template match="PROGRESS | CLOSED | COMPLETE">
  <Event Name="{local-name()}">
    <xsl:apply-templates />
  </Event>
</xsl:template>

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

</xsl:stylesheet>
Tony Graham
  • 7,306
  • 13
  • 20
1
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xi="http://www.w3.org/2001/XInclude">
  <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
  <xsl:template match="/Events">
    <xsl:element name="Events">
      <xsl:for-each select="*">
        <xsl:element name="Event">
          <xsl:attribute name="Name">
            <xsl:value-of select="local-name()"/>
          </xsl:attribute>
          <xsl:copy-of select="*"/>
        </xsl:element>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

This should do the job. A little bit more verbose than the previous answer, though.

zx485
  • 28,498
  • 28
  • 50
  • 59