2017-02-28 79 views
2

鑑於以下XML:複製指定的元素和孩子和屬性

<Products> 
    <Batteries> 
     <Name Value="Triple A"/> 
     <Colour Value="Red"/> 
    </Batteries> 
    <Cups> 
     <Name Value="Mugs"/> 
     <Colour Value="Blue"/> 
     <Logo> 
      <Company Value="Super Clean!"/> 
      <Colour Value="Red"/> 
     </Logo> 
    </Cups> 
    <Cups> 
     <Name Value="Teacups"/> 
     <Colour Value="Orange"/> 
     <Handle Value="Dainty"/> 
     <Logo> 
      <Company Value="Lovely teas"/> 
      <Colour Value="Red"/> 
     </Logo> 
    </Cups> 
</Products> 

我將如何複製Cups元素及其所有子元素他們所有的屬性? Cups的後代幾乎可以是任何東西(例如可以添加新元素並且我仍然希望它被複制),並且它們也可以具有附加屬性。

因此,在這種情況下,我需要的輸出是:

<Products> 
    <Cups> 
     <Name Value="Mugs"/> 
     <Colour Value="Blue"/> 
     <Logo> 
      <Company Value="Super Clean!"/> 
      <Colour Value="Red"/> 
     </Logo> 
    </Cups> 
    <Cups> 
     <Name Value="Teacups"/> 
     <Colour Value="Orange"/> 
     <Handle Value="Dainty"/> 
     <Logo> 
      <Company Value="Lovely teas"/> 
      <Colour Value="Red"/> 
     </Logo> 
    </Cups> 
</Products> 

經過一番揮舞圍繞我有這樣的:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
    <xsl:template match="@*|node()"> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:template> 
    <xsl:template match="/"> 
     <Products> 
      <xsl:apply-templates/> 
     </Products> 
    </xsl:template> 
    <xsl:template match="Cups|Cups//*"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

但它不是整個屬性的輸出複製。

注意:這不是我的XML,它沒有模式,但我確信會有Cups

回答

3

問題是與此模板....

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

它會忽略所有屬性和文本節點(以及沒有被你的另一模板匹配的元素)。

你可以做什麼,簡直就是改變你的模板匹配「杯|杯// *」來使用,而不是xsl:copy-of ...

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

然而,這看起來你真正要做的實際上是刪除Batteries節點及其後代。如果是這樣,使用身份模板複製一切,只是有單一的模板忽略Batteries,像這樣......

試試這個XSLT

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

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

    <xsl:template match="Batteries" /> 
</xsl:stylesheet> 

編輯:在回答你的評論,如果要複製元素的畢竟是少數,試試這個方法,而不是...

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

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

    <xsl:template match="Products/*" /> 

    <xsl:template match="Cups|Spoons" priority="2"> 
     <xsl:call-template name="identity" /> 
    </xsl:template> 
</xsl:stylesheet> 

這將刪除所有元素Products下與CupsSpoons例外。

+0

您的更新和非常正確的'杯'匹配模板做了這份工作!我無法真正做一個模板來刪除'Batteries',因爲我非常人爲的例子並沒有表明在我的實際XML中有很多不同的其他元素,我想複製的元素是少數 - 但是你的答案符合該法案完美。非常感謝!踢自己沒有意識到我自己:) –

+0

如果有幫助,我已經擴大了我的答案,以顯示一個稍微不同的方法,以便您希望複製的元素在少數情況下。 –

+0

這是非常有用的,我希望我可以upvote多次! –

相關問題