2

新しい要素に含める必要があるシーケンシャル ノードのセットがあります。例:

  <root>
    <c>cccc</c>
    <a gr="g1">aaaa</a>    <b gr="g1">1111</b>
    <a gr="g2">bbbb</a>   <b gr="g2">2222</b>
  </root>

これはタグで囲む必要がありfold、(XSLT の後) は次のようになります。

  <root>
    <c>cccc</c>
    <fold><a gr="g1">aaaa</a>    <b gr="g1">1111</b></fold>
    <fold><a gr="g2">bbbb</a>   <b gr="g2">2222</b></fold>
  </root>

だから、私は「グループ化のためのラベル」(@gr)を持っていますが、正しい折りタグを作成する方法を想像していません.


この質問またはこの他の質問の手がかりを使用しようとしています...しかし、「グループ化のラベル」があるため、私のソリューションではkey()関数を使用する必要がないことを理解しています。

私の非一般的な解決策は次のとおりです。

   <xsl:template match="/">
       <root>
       <xsl:copy-of select="root/c"/>
       <fold><xsl:for-each select="//*[@gr='g1']">
             <xsl:copy-of select="."/>
       </xsl:for-each></fold>

       <fold><xsl:for-each select="//*[@gr='g2']">
             <xsl:copy-of select="."/>
       </xsl:for-each></fold>

       </root>
   </xsl:template>

一般的な解決策 (!) が必要です。すべての @gr でループし、@gr を持たないすべてのコンテキスト (ID) に対処します...おそらくID 変換を使用します。

もう 1 つの (将来の) 問題は、折り畳みの折り畳みを使用して、これを再帰的に行うことです。

4

1 に答える 1

2

XSLT 1.0 では、このようなことを処理する標準的な手法は Muenchian グループ化と呼ばれ、ノードをグループ化する方法を定義するキーgenerate-idの使用と、各グループの最初のノードのみを抽出するためのトリックを使用して、グループ全体。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:strip-space elements="*" />
  <xsl:output indent="yes" />
  <xsl:key name="elementsByGr" match="*[@gr]" use="@gr" />

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

  <!-- match the first element with each @gr value -->
  <xsl:template match="*[@gr][generate-id() =
         generate-id(key('elementsByGr', @gr)[1])]" priority="2">
    <fold>
      <xsl:for-each select="key('elementsByGr', @gr)">
        <xsl:call-template name="identity" />
      </xsl:for-each>
    </fold>
  </xsl:template>

  <!-- ignore subsequent ones in template matching, they're handled within
       the first element template -->
  <xsl:template match="*[@gr]" priority="1" />
</xsl:stylesheet>

これにより、目的のグループ化が実現しますが、非一般的なソリューションと同様に、要素ab要素の間のインデントと空白テキストノードが保持されません。つまり、

<root>
  <c>cccc</c>
  <fold>
    <a gr="g1">aaaa</a>
    <b gr="g1">1111</b>
  </fold>
  <fold>
    <a gr="g2">bbbb</a>
    <b gr="g2">2222</b>
  </fold>
</root>

XSLT 2.0 を使用できた場合、すべてが 1 つになることに注意してくださいfor-each-group

<xsl:template match="root">
  <xsl:for-each-group select="*" group-adjacent="@gr">
    <xsl:choose>
      <!-- wrap each group in a fold -->
      <xsl:when test="@gr">
        <fold><xsl:copy-of select="current-group()" /></fold>
      </xsl:when>
      <!-- or just copy as-is for elements that don't have a @gr -->
      <xsl:otherwise>
        <xsl:copy-of select="current-group()" />
      </xsl:otherwise>
    </xsl:choose>
  </xsl:for-each-group>
</xsl:template>
于 2013-08-19T11:01:49.997 に答える