2012-04-23 41 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