2011-04-14 144 views
4

我有一個看起來像這樣將XML元素到另一個元素使用XSLT

<executionPlan name="Test" > 
<paramList> 
    <param name="param1" default=""/> 
</paramList> 

<varList> 
    <var name="bla" default=":[param1]"/> 
</varList> 

<simpleSteps limitToHostSet="bla"> 
    <execNative> 
     <exec cmd="/bin/sh"/> 
    </execNative> 
</simpleSteps> 

的XML,我需要改變它看起來像這樣:

<executionPlan name="Test" > 
<paramList> 
    <param name="param1" default=""/> 
</paramList> 

<simpleSteps limitToHostSet="bla"> 
    <varList> 
     <var name="bla" default=":[param1]"/> 
    </varList> 
    <execNative> 
     <exec cmd="/bin/sh"/> 
    </execNative> 
</simpleSteps> 

正如你所看到的,varList元素需要嵌套在開頭後面的simpleSteps元素中 標籤。 simpleSteps內部可能有其他varList元素,不能更改。

任何想法如何實現與XSLT?我是XSLT的新手,並且一整天都徒勞無功......任何幫助都會得到真正的讚賞。

魯茲

+0

只有第一個'simpleSteps'中的第一個'varList'? 'simpleSteps'''varList'子應該合併還是留作兄弟? – 2011-04-14 16:01:08

+0

好問題,+1。查看我的答案,獲得更簡單,更簡單的解決方案和廣泛的解釋。 – 2011-04-15 03:38:02

回答

4

下面的樣式表:

<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="varList[following-sibling::*[1][self::simpleSteps]]" /> 
    <xsl:template match="simpleSteps"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*" /> 
      <xsl:copy-of select="preceding-sibling::varList[1]" /> 
      <xsl:apply-templates select="node()" /> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

在此輸入:

<executionPlan name="Test"> 
    <paramList> 
     <param name="param1" default="" /> 
    </paramList> 
    <varList> 
     <var name="bla" default=":[param1]" /> 
    </varList> 
    <varList> 
     <var name="bla2" default=":[param2]" /> 
    </varList> 
    <simpleSteps limitToHostSet="bla"> 
     <execNative> 
      <exec cmd="/bin/sh" /> 
     </execNative> 
    </simpleSteps> 
</executionPlan> 

產地:

<executionPlan name="Test"> 
    <paramList> 
     <param name="param1" default="" /> 
    </paramList> 
    <varList> 
     <var name="bla" default=":[param1]" /> 
    </varList> 
    <simpleSteps limitToHostSet="bla"> 
     <varList> 
      <var name="bla2" default=":[param2]" /> 
     </varList> 
     <execNative> 
      <exec cmd="/bin/sh" /> 
     </execNative> 
    </simpleSteps> 
</executionPlan> 

編輯:只有緊接前面的varList被移入其關聯的simpleSteps。所有其他varList元素都是通過不變來複制的。

突然不清楚這是否是所需的行爲,或者simpleSteps元素中可能有多個varList元素應該保持不變。看我爲這種情況下,原來的解決方案:

<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="varList" /> 
    <xsl:template match="simpleSteps"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*" /> 
      <xsl:copy-of select="../varList" /> 
      <xsl:apply-templates select="node()" /> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

在此輸入:

<executionPlan name="Test"> 
    <paramList> 
     <param name="param1" default="" /> 
    </paramList> 
    <varList> 
     <var name="bla" default=":[param1]" /> 
    </varList> 
    <simpleSteps limitToHostSet="bla"> 
     <varList> 
      <var name="bla7" default=":[param7]" /> 
     </varList> 
     <execNative> 
      <exec cmd="/bin/sh" /> 
     </execNative> 
    </simpleSteps> 
</executionPlan> 

產地:

<executionPlan name="Test"> 
    <paramList> 
     <param name="param1" default="" /> 
    </paramList> 
    <simpleSteps limitToHostSet="bla"> 
     <varList> 
      <var name="bla" default=":[param1]" /> 
     </varList> 
     <varList> 
      <var name="bla7" default=":[param7]" /> 
     </varList> 
     <execNative> 
      <exec cmd="/bin/sh" /> 
     </execNative> 
    </simpleSteps> 
</executionPlan> 
2

這是一個簡單的和更短的解決方案

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<xsl:template match="simpleSteps/*[1]"> 
    <xsl:copy-of select="/*/varList[1]"/> 
    <xsl:call-template name="identity"/> 
</xsl:template> 

<xsl:template match="/*/varList[1]"/> 
</xsl:stylesheet> 

當所提供的XML文檔應用:

<executionPlan name="Test" > 
    <paramList> 
     <param name="param1" default=""/> 
    </paramList> 
    <varList> 
     <var name="bla" default=":[param1]"/> 
    </varList> 
    <simpleSteps limitToHostSet="bla"> 
     <execNative> 
      <exec cmd="/bin/sh"/> 
     </execNative> 
    </simpleSteps> 
</executionPlan> 

完全想要的,正確的結果產生:

<executionPlan name="Test"> 
    <paramList> 
     <param name="param1" default=""/> 
    </paramList> 
    <simpleSteps limitToHostSet="bla"> 
     <varList> 
     <var name="bla" default=":[param1]"/> 
     </varList> 
     <execNative> 
     <exec cmd="/bin/sh"/> 
     </execNative> 
    </simpleSteps> 
</executionPlan> 

說明

  1. identity rule /模板「按原樣」複製每個節點。只有兩個例外,下面解釋。

  2. 僅匹配top元素的第一個子元素的覆蓋模板沒有主體 - 這有效地取消了此元素的標識模板的複製操作。

  3. 說的simpleSteps第一子元素相匹配的首要模板做了兩兩件事:1)它複製棧頂元素的希望varList(子)元素,然後b)調用的身份模板將自身複製到輸出。