3

属性「f」に従って、出力xmlを要素「c」に対してグループ化する必要があります。これが私の入力xmlとxsltです。グループを1回だけ発生させ、他のノードをそのまま出力にコピーする必要があります。私が試したxsltは、入力xml全体をコピーします。したがって、c要素と'f'の同じ属性値を持つ要素が2つ以上ある場合は、そのグループの最初の出現を出力に含める必要があります。欲しい結果もコピーされます。

入力xml

<M>
   <a>
      <b>
         <c f="123">
            <d>Al</d>
            <e NO="678">
               <f>Y</f>
               <g>
                  <h>FTO</h>
               </g>
            </e>
         </c>
      </b>
   </a>
  <a>
    <b>
      <c f="123">
        <d>Al</d>
        <e NO="678">
          <f>Y</f>
          <g>
            <h>FTO</h>
          </g>
        </e>
      </c>
    </b>
  </a>
  <a>
    <b>
      <c f="567">
        <d>Al</d>
        <e NO="678">
          <f>Y</f>
          <g>
            <h>FTO</h>
          </g>
        </e>
      </c>
    </b>
  </a>
  <a>
    <b>
      <somethingelse></somethingelse>
    </b>
  </a>
</M>

出力xmlが必要

<M>
  <a>
    <b>
      <c f="123">
        <d>Al</d>
        <e NO="678">
          <f>Y</f>
          <g>
            <h>FTO</h>
          </g>
        </e>
      </c>
    </b>
  </a>
  <a>
    <b>
      <c f="567">
        <d>Al</d>
        <e NO="678">
          <f>Y</f>
          <g>
            <h>FTO</h>
          </g>
        </e>
      </c>
    </b>
  </a>
  <a>
    <b>
      <somethingelse></somethingelse>
    </b>
  </a>
</M>

xslt試してみました

<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="mykey" match="c"
   use="@f"/>

  <xsl:template match=
  "c[generate-id()
      =
       generate-id(key('mykey',@f)[1])
      ]
  ">



    <xsl:text/>
    <xsl:copy-of select="key('mykey',@f)[1]"/>
  </xsl:template>
  <xsl:template match="node()|@*">
        <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
4

4 に答える 4

2

この変換

<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="kAByC-F" match="a" use="*/c/@f"/>

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

     <xsl:template match=
      "a[*/c
       and
         not(generate-id()
            =
             generate-id(key('kAByC-F', */c/@f)[1])
             )
        ]"/>
</xsl:stylesheet>

提供されたXMLドキュメントに適用した場合

<M>
   <a>
      <b>
         <c f="123">
            <d>Al</d>
            <e NO="678">
               <f>Y</f>
               <g>
                  <h>FTO</h>
               </g>
            </e>
         </c>
      </b>
   </a>
  <a>
    <b>
      <c f="123">
        <d>Al</d>
        <e NO="678">
          <f>Y</f>
          <g>
            <h>FTO</h>
          </g>
        </e>
      </c>
    </b>
  </a>
  <a>
    <b>
      <c f="567">
        <d>Al</d>
        <e NO="678">
          <f>Y</f>
          <g>
            <h>FTO</h>
          </g>
        </e>
      </c>
    </b>
  </a>
  <a>
    <b>
      <somethingelse></somethingelse>
    </b>
  </a>
</M>

必要な正しい結果を生成します

<M>
   <a>
      <b>
         <c f="123">
            <d>Al</d>
            <e NO="678">
               <f>Y</f>
               <g>
                  <h>FTO</h>
               </g>
            </e>
         </c>
      </b>
   </a>
   <a>
      <b>
         <c f="567">
            <d>Al</d>
            <e NO="678">
               <f>Y</f>
               <g>
                  <h>FTO</h>
               </g>
            </e>
         </c>
      </b>
   </a>
   <a>
      <b>
         <somethingelse/>
      </b>
   </a>
</M>

説明

Muenchianグループ化方法の適切な使用。

于 2012-06-13T01:55:42.837 に答える
1

c簡単な解決策は、次のすべてのノードに空のテンプレートを追加することです。

<xsl:template match="c[generate-id() = generate-id(key('mykey',@f)[position() &gt; 1])]" />
于 2012-06-12T17:21:45.500 に答える
0

要素を照合し、サブ要素に同じ属性を<a>持つ先行する兄弟があるかどうかを確認できます。存在する場合は、特定の値の重複(その値の最初の出現ではない特定の値の出現) が見つかり、ID テンプレートをオーバーライドして要素をスキップできます。f<c>ff

<xsl:stylesheet version="1.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="/M/a[b/c/@f = preceding-sibling::a/b/c/@f]"/>

</xsl:stylesheet>

このソリューションの利点は、キーまたは ID の生成に関する知識が必要ないことです。基本的な XPath 軸機能でのみ機能します。ただし、比較する要素がすべて同じ入れ子の深さ/同じ相対要素階層にない場合は、少し複雑になる可能性があります。

PS:<xsl:strip-space elements="*"/>テストできなかったため要素を削除しました (私の Xml プロセッサは、ファイルではなく読み取り可能なストリームを渡す場合にのみ使用できると主張しました)。

于 2012-06-12T17:49:13.043 に答える
0

c のすべての値を互いに区別できる形式で変数に保存し、c に遭遇するたびに、その値が変数内に含まれているかどうかを確認することも考えられます。そうである場合は、次のノードにスキップします。そうでない場合は、現在のノードの処理を続行します。

より具体的な情報が必要な場合は教えてください

EDIT:代わりに、おそらくより簡単な方法(私は最近NAntを使用しているので、NAnt戦略を提供するかもしれません)は、すべてのノードをs値でソートすることです。次に、cの現在の値を格納する変数を用意し、見ている値が格納された値と等しくなくなるまで比較します。次に、値を再割り当てして、もう一度やり直してください!

于 2012-06-12T17:07:44.720 に答える