2012-04-23 60 views
1

刪除與相同屬性相同的節點同一母公司下的XML我要改造這個XML輸入:使用XSLT

<root> 
    <node id="a"> 
     <section id="a_1" method="run"> 
      <item id="0" method="a"> 
       <attribute> 
        <color>Red</color> 
        <status>1</status> 
        <condition>good</condition> 
       </attribute> 

      </item> 

      <item id="0" method="a"> 
       <attribute> 
        <color>Red</color> 
        <status>1</status> 
        <condition>good</condition> 
       </attribute> 

      </item> 
     </section> 

     <section id="a_2" method="run"> 
      <item id="0" method="a"> 
       <attribute> 
        <color>Red</color> 
        <status>1</status> 
        <condition>good</condition> 
       </attribute> 

      </item> 
     </section> 

    </node> 

    <node id="b"> 
     <section id="b_1" method="create"> 
      <user id="b_1a" method="x"> 
       <attribute> 

        <origin>us</origin> 
       </attribute> 

      </user> 
      <user id="b_1a" method="x"> 
       <attribute> 
        <origin>us</origin> 
       </attribute> 
      </user> 
      <user id="b_1b"> 
       <attribute>a</attribute> 
      </user> 
     </section> 

     <section id="b_2"> 
      <user id="b_1a" method="x"> 
       <attribute> 
        <name>John</name> 
        <origin>us</origin> 
       </attribute> 
      </user> 
     </section> 
    </node> 
</root> 

這裏是預期輸出:

<root> 
    <node id="a"> 
     <section id="a_1" method="run"> 
      <item id="0" method="a"> 
       <attribute> 
        <color>Red</color> 
        <status>1</status> 
        <condition>good</condition> 
       </attribute>      
      </item>    
     </section> 

     <section id="a_2" method="run"> 
      <item id="0" method="a"> 
       <attribute> 
        <color>Red</color> 
        <status>1</status> 
        <condition>good</condition> 
       </attribute> 

      </item> 
     </section> 
    </node> 

    <node id="b"> 
     <section id="b_1" method="create"> 
      <user id="b_1a" method="x"> 
       <attribute> 
        <origin>us</origin> 
       </attribute> 

      </user> 

      <user id="b_1b"> 
       <attribute>a</attribute> 
      </user> 
     </section> 

     <section id="b_2"> 
      <user id="b_1a" method="x"> 
       <attribute> 
        <name>John</name> 
        <origin>us</origin> 
       </attribute> 
      </user> 
     </section> 
    </node> 
</root> 

注:重複意味着所有的孩子/孩子具有相同的價值,只要它是同一父母(節點id和方法相同),節點就可以有一個或多個孩子,我們可以假定它總是在同一節(id和方法相同)。

這是可以做到的嗎?請賜教

非常感謝。

歡呼聲, 約翰

+0

還增加了XSLT 2.0溶液。 – 2012-04-23 03:40:13

回答

2

I.這XSLT 1.0轉化

<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:key name="kElemWithAttribs" match="*[@id and @method]" 
     use="concat(generate-id(..), '+', name(), '+', @id, '+', @method)"/> 

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

    <xsl:template match= 
     "*[@id and @method 
     and 
     not(generate-id() 
      = 
      generate-id(key('kElemWithAttribs', 
          concat(generate-id(..), 
          '+',name(), '+', @id, '+', @method) 
          )[1] 
         ) 
      ) 
     ]"/> 
</xsl:stylesheet> 

當施加到所提供的源XML文檔:

<root> 
    <node id="a"> 
     <section id="a_1" method="run"> 
      <item id="0" method="a"> 
       <attribute> 
        <color>Red</color> 
        <status>1</status> 
        <condition>good</condition> 
       </attribute> 
      </item> 
      <item id="0" method="a"> 
       <attribute> 
        <color>Red</color> 
        <status>1</status> 
        <condition>good</condition> 
       </attribute> 
      </item> 
     </section> 
     <section id="a_2" method="run"> 
      <item id="0" method="a"> 
       <attribute> 
        <color>Red</color> 
        <status>1</status> 
        <condition>good</condition> 
       </attribute> 
      </item> 
     </section> 
     <section id="a_2" method="run"> 
      <item id="0" method="a"> 
       <attribute> 
        <color>Red</color> 
        <status>1</status> 
        <condition>good</condition> 
       </attribute> 
      </item> 
     </section> 
    </node> 
    <node id="b"> 
     <section id="b_1" method="create"> 
      <user id="b_1a" method="x"> 
       <attribute> 
        <origin>us</origin> 
       </attribute> 
      </user> 
      <user id="b_1a" method="x"> 
       <attribute> 
        <origin>us</origin> 
       </attribute> 
      </user> 
      <user id="b_1b"> 
       <attribute>a</attribute> 
      </user> 
     </section> 
     <section id="b_2"> 
      <user id="b_1a" method="x"> 
       <attribute> 
        <name>John</name> 
        <origin>us</origin> 
       </attribute> 
      </user> 
     </section> 
    </node> 
</root> 

產生希望,更正結果:

<root> 
    <node id="a"> 
     <section id="a_1" method="run"> 
     <item id="0" method="a"> 
      <attribute> 
       <color>Red</color> 
       <status>1</status> 
       <condition>good</condition> 
      </attribute> 
     </item> 
     </section> 
     <section id="a_2" method="run"> 
     <item id="0" method="a"> 
      <attribute> 
       <color>Red</color> 
       <status>1</status> 
       <condition>good</condition> 
      </attribute> 
     </item> 
     </section> 
    </node> 
    <node id="b"> 
     <section id="b_1" method="create"> 
     <user id="b_1a" method="x"> 
      <attribute> 
       <origin>us</origin> 
      </attribute> 
     </user> 
     <user id="b_1b"> 
      <attribute>a</attribute> 
     </user> 
     </section> 
     <section id="b_2"> 
     <user id="b_1a" method="x"> 
      <attribute> 
       <name>John</name> 
       <origin>us</origin> 
      </attribute> 
     </user> 
     </section> 
    </node> 
</root> 

說明:正確使用的Muenchian method for grouping,使用複合密鑰:

  1. 身份規則拷貝每一個節點 「原樣」。

  2. xsl:key定義將元素組與一個字符串鍵值相關聯。如此定義的任何組由所有具有idmethod屬性的元素組成,並且(全部在組中)具有相同的父項,相同的名稱,id屬性的相同字符串值和method的相同字符串值屬性。

  3. 有一個模板覆蓋了標識模板。它匹配具有idmethod屬性且不是各自組中第一個(按文檔順序)元素的任何元素。由於該模板沒有主體,因此所有這些匹配的元素根本不會被處理,也不會被複制到輸出中(我們可以說它們已被「刪除」)。

  4. 由於上面的3.因此,只有作爲其組的第一個元素的元素纔會與覆蓋模板不匹配。因此,這些元素由身份模板匹配並複製到輸出 - 完全按需要。


II。 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="*[@id]"> 
     <xsl:copy> 
     <xsl:apply-templates select="@*"/> 

     <xsl:for-each-group select="*" group-by= 
     "concat(generate-id(..), '+', name(), '+', @id, '+', @method)"> 
      <xsl:apply-templates select="."/> 
     </xsl:for-each-group> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

說明:正確使用的xsl:for-each-groupgroup-by屬性。

+0

太棒了!非常感謝你的時間。 – John 2012-04-23 03:36:55

+1

@約翰:不客氣。我還添加了一個XSLT 2.0解決方案,這可能對您很有意思。 – 2012-04-23 03:41:31

+0

謝謝。你介意向我解釋比賽的工作原理嗎? – John 2012-04-23 03:49:45