4

要素の数に基づいて、ノードを変換しようとしています。つまり、5、次にノードを閉じて、新しいノードを再度開きます。以下の例を参照してください

<root>
  <branch>
    <foo>bar</foo>
    <foo>bar2</foo>
    <foo>bar3</foo>
    <foo>bar4</foo>
    <foo>bar5</foo>
    <foo>bar6</foo>
    <foo>bar7</foo>
  </branch>
<root>

になるはずです

<root>
  <branch>
    <foo>bar</foo>
    <foo>bar2</foo>
    <foo>bar3</foo>
    <foo>bar4</foo>
    <foo>bar5</foo>
   <branch>
   </branch>
    <foo>bar6</foo>
    <foo>bar7</foo>
  </branch>
<root>

XSLTでこれを行う方法を教えてください。

4

2 に答える 2

5

I.このXSLT1.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:template match="/*">
  <root>
   <xsl:apply-templates/>
  </root>
 </xsl:template>

 <xsl:template match="foo[position() mod 5 = 1]">
  <branch>
    <xsl:copy-of select=
     ". | following-sibling::*[not(position() > 4)]"/>
  </branch>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

提供されたXMLドキュメントに適用された場合(整形式に修正):

<root>
    <branch>
        <foo>bar</foo>
        <foo>bar2</foo>
        <foo>bar3</foo>
        <foo>bar4</foo>
        <foo>bar5</foo>
        <foo>bar6</foo>
        <foo>bar7</foo>
    </branch>
</root>

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

<root>
   <branch>
      <foo>bar</foo>
      <foo>bar2</foo>
      <foo>bar3</foo>
      <foo>bar4</foo>
      <foo>bar5</foo>
   </branch>
   <branch>
      <foo>bar6</foo>
      <foo>bar7</foo>
   </branch>
</root>

説明

これは「位置グループ化」の場合であり、グループのすべての開始要素が5タプルの最初の要素です(したがって、その位置は次の条件を満たすposition() mod 5 = 1


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="/*">
  <root>
    <xsl:for-each-group select="*/*"
         group-adjacent="(position() -1) idiv 5">
          <branch>
            <xsl:sequence select="current-group()"/>
          </branch>
    </xsl:for-each-group>
  </root>
 </xsl:template>
</xsl:stylesheet>

このXSLT2.0変換を同じXM​​Lドキュメント(上記)に適用すると、同じ必要な正しい結果が生成されます。

説明

属性と関数を使用した<xsl:for-each-group>XSLT2.0命令の適切な使用。group-adjacentcurrent-group()

于 2012-06-03T18:45:42.147 に答える
0

XSLT には、ノードを「開く」または「閉じる」などの操作はありません。処理モデルについて間違った考えを持っています。頭の中でそれを理解するまで、この種の問題を解決するのは非常に困難です。特に、XSLT が (概念的に) 開始タグと終了タグを含む字句 XML を含むファイルではなく、結果ツリーを作成していることを理解していません。必要なことは、ソース ツリーの 5 つのノードの各グループに対応する結果ツリーに 1 つのノードを作成することです (または、同じように、複数の位置にあるソース ツリーの各ノードに対応する結果ツリーに 1 つのノードを作成することです)。 5の)。

Dimitre の解決策は完全に正しいですが、個人的には、自分の考えのどこが間違っていたのかを説明せずに実用的な解決策を提供することは、質問に答える最善の方法ではないと思います。

于 2012-06-04T16:54:08.597 に答える