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

注:重複すべての子/子が同じ値を持つことを意味します。ノードは同じ親である限り、1つ以上の子を持つことができます(idとメソッドは同じです)。方法は同じです)。

これは可能ですか?教えてください

ありがとうございます。

歓声、 ジョン

+0

XSLT 2.0ソリューションも追加されました。 –

答えて

2

I.このXSLT 1.0変換

<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> 

が望んで生成します。提供されたソースXML文書に適用

<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> 

、正しい結果:

<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の定義は、要素のグループを文字列のキー値に関連付けます。そのように定義されたグループは、id属性とmethod属性の両方を持つすべての要素で構成され、同じ名前、同じ名前、id属性の同じ文字列値、同じ文字列値のmethod属性。

  3. IDテンプレートを上書きするテンプレートが1つあります。 idmethodの両方の属性を持ち、それぞれのグループの最初の(ドキュメント順の)要素ではない要素に一致します。このテンプレートにはボディがないので、このようにマッチした要素はすべて処理されず、出力にコピーされません(削除されたとも言えます)。

  4. 上記のため、グループの最初の要素である要素だけが、上書きテンプレートと一致しません。したがって、これらの要素はIDテンプレートによって照合され、必要に応じて正確に出力にコピーされます。


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> 

説明group-by属性を持つxsl:for-each-groupの適切な使用。

+0

恐ろしい!ご清聴ありがとうございました。 – John

+1

@ジョン:どうぞよろしくお願いいたします。また、興味深いXSLT 2.0ソリューションを追加しました。 –

+0

ありがとうございます。マッチの仕組みを私に説明してもらえますか? – John

関連する問題