2011-09-02 12 views
3

的我想變換XSL只遞歸複製一些元件和除去一些後代

<?xml version="1.0" ?> 
<mydoc> 
    <file> 
     <colors> 
      <blue /> 
      <red /> 
      <green /> 
     </colors> 
     <secret> 
      <username /> 
      <password /> 
     </secret> 
    </file> 
</mydoc> 

<?xml version="1.0" ?> 
<colors> 
    <blue /> 
    <red /> 
</colors> 

在普通的英語,我想的顏色元件遞歸複製,包括文本,忽略XML文檔的其餘部分並丟棄綠色元素。

有一些解決方案適用於上述示例,但如果XML稍有不同,則會失敗。例如通過添加顏色元素下的元件,或其他元件,其不處於顏色元件的層次結構,或文本是在顏色元素的範圍(GOOD TEXT)和另一個不在其範圍內的文本(不良文本)。

<?xml version="1.0" ?> 
<mydoc> 
    <file> 
     <colors> 
      <nest> 
       <blue /> 
       <red /> 
       <green /> 
      </nest> 
      GOOD TEXT 
     </colors> 
     <secret> 
      <username /> 
      <password /> 
     </secret> 
     BAD TEXT 
    </file> 
    <other>BAD TEXT TWO</other> 
</mydoc> 

我最感興趣的是一個通用的解決方案,而不是定製到這裏介紹的例子。

回答

2

這種新的變換一般足以複製的色彩元素不論其父母是

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

    <xsl:template match="/mydoc/file/colors"> 
     <xsl:variable name="colors_parent" 
      select="local-name(.//green/parent::*)"/> 
     <xsl:copy> 
      <xsl:copy-of 
       select=".//*[local-name()=$colors_parent]/*[not(self::green)]"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="text()"/> 

</xsl:stylesheet> 

我也排除了所有可能的文本元素。目前還不清楚您是否想保留「GOOD TEXT」文本節點。然而,現在您應該很容易地將轉換適應新的要求。例如,如果你想保留任何文本節點下顏色元素,你可以改變使用該轉換:身份規則的

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

    <xsl:template match="/mydoc/file/colors"> 
     <xsl:variable name="colors_parent" 
      select="local-name(.//green/parent::*)"/> 
     <xsl:copy> 
      <xsl:copy-of 
       select=".//*[local-name()=$colors_parent]/*[not(self::green)] 
         | .//text()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="text()"/> 

</xsl:stylesheet> 

使用(它複製元素)

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

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

    <xsl:template match="mydoc"> 
     <xsl:apply-templates select="file/colors"/> 
    </xsl:template> 

    <xsl:template match="green"/> 

</xsl:stylesheet> 
+1

我試圖將解決方案應用於真實世界的示例,但失敗了。我總結了我在更新問題時發現的問題,第二個例子包括輕微的變化。您的第二個解決方案更強大並且成功。非常感謝。 –

+0

我已經更新了第一個解決方案,並保留了身份規則,因爲它是公認的規則。 –

1
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="no"/> 

    <xsl:template match="/"> 
     <colors> 
      <xsl:apply-templates select="//colors/*[not(self::green)]"/> 
     </colors> 
    </xsl:template> 

    <xsl:template match="*"> 
     <xsl:copy-of select="."/> 
    </xsl:template> 

</xsl:stylesheet> 

輸出:

<colors> 
    <blue /> 
    <red /> 
</colors> 
+1

儘管它與第一個示例一起使用,但它不足以與第二個示例匹配。你能想到更通用的解決方案嗎? –