XSLT - 转换XML元素名称并添加属性

时间:2014-10-21 11:39:15

标签: xml xslt

我有一个XML文件从第三方发送给我,格式如下:

<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>

是否有办法使用XSLT将Events元素的子节点转换为名为Event,并且具有名为Name的属性,其中包含当前子元素名称。我正在寻找的输出是:

<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>

我已经在网上看了很多,但却找不到如何做到这一点。非常感谢!

2 个答案:

答案 0 :(得分:1)

作为身份样式表的补充:

<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>

答案 1 :(得分: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>

这应该可以胜任。但是,比前一个答案更冗长。