2012-07-10 98 views
1

如果我有這樣的輸入:如何使用XSLT將此子元素組合在一起?

<root> 
    <library id="L1"> 
     <shelf1 id="1"> 
      <book id="1" category="science"> 
       <attributes>      
        <year>2000</year> 
       </attributes> 
       <attributes> 
        <author>xx</author> 
        <year>2010</year> 
        <isbn>001</isbn> 
       </attributes> 
       <attributes> 
        <author>yy</author> 
        <publisher>zz</publisher> 
        <isbn>002</isbn> 
       </attributes> 
       <other>y</other> 
      </book> 
      <book id="2" category="science"> 
       ... 
      </book> 
     </shelf1> 

     <shelf2>...</shelf2> 
    </library> 
</root> 

expetced輸出:

<root> 
    <library id="L1"> 
     <shelf1 id="1"> 
      <book id="1" category="science"> 
       <attributes> 
        <author>yy</author>      
        <publisher>zz</publisher> 
        <isbn>002</isbn> 
        <year>2010</year> 
       </attributes> 
       <other>y</other> 
      </book> 
      <book id="2" category="science"> 
       ... 
      </book> 
     </shelf1> 

     <shelf2>...</shelf2> 
    </library> 
</root> 

我需要的元素 '屬性' 結合在一起。如果存在兩個或更多個屬性,當屬性的子項從未存在時,我們將該子項作爲新信息,但如果它以前存在,我們只需使用最新值。

如何做這樣的轉型,XSLT 1.0或2.0?非常感謝您的幫助。

約翰

回答

2

這種變換(XSLT 2.0):

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

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

<xsl:template match="book[attributes]"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*"/> 
    <attributes> 
     <xsl:for-each-group select="attributes/*" group-by="name()"> 
     <xsl:sort select="current-grouping-key()"/> 
     <xsl:apply-templates select="."/> 
     </xsl:for-each-group> 
    </attributes> 
    <xsl:apply-templates select="*[not(self::attributes)]"/> 
    </xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

當所提供的XML文檔應用:

<root> 
    <library id="L1"> 
     <shelf1 id="1"> 
      <book id="1" category="science"> 
       <attributes> 
        <year>2000</year> 
       </attributes> 
       <attributes> 
        <author>xx</author> 
        <year>2010</year> 
        <isbn>001</isbn> 
       </attributes> 
       <attributes> 
        <author>yy</author> 
        <publisher>zz</publisher> 
        <isbn>002</isbn> 
       </attributes> 
       <other>y</other> 
      </book> 
      <book id="2" category="science"> 
      ... 
      </book> 
     </shelf1> 
     <shelf2>...</shelf2> 
    </library> 
</root> 

產生想要的,正確的結果

<root> 
     <library id="L1"> 
      <shelf1 id="1"> 
        <book id="1" category="science"> 
      <attributes> 
       <author>xx</author> 
       <isbn>001</isbn> 
       <publisher>zz</publisher> 
       <year>2000</year> 
      </attributes> 
      <other>y</other> 
     </book> 
        <book id="2" category="science"> 
      ... 
      </book> 
      </shelf1> 
      <shelf2>...</shelf2> 
     </library> 
</root> 

說明

  1. 正確使用和身份規則壓倒一切。

  2. 正確使用XSLT 2.0指令xsl:for-each-group,屬性爲group-by

  3. 正確使用XSLT 2.0函數current-grouping-key()和XPath函數name()

+0

謝謝大家的整潔和真棒解決方案。 – John 2012-07-11 05:04:19

+0

@約翰,不客氣。 – 2012-07-11 05:25:32