3

3つの個別のリストに分割したい要素のリストがあります。最終結果は次のようになります。

<ul>
    <li>element</li>
    <li>element</li>
</ul>
<ul>
    <li>element</li>
    <li>element</li>
</ul>
<ul>
    <li>element</li>
    <li>element</li>
</ul>

私のXSLTはこのようなものですが、挿入</ul>できず、より小さい記号(<)を挿入できないため、機能しません。

<ul>
    <xsl:for-each select="$myroot/item">
        <li></li>

        <xsl:if test="position() mod $maxItemsPerColumn = 0">
            <!-- I want to close my ul, and start a new one here, but it doesn't work! -->
        </xsl:if>
    </xsl:for-each>
</ul>

何か案は?前もって感謝します!

4

4 に答える 4

9

再帰のような特別なことをする必要はありません。そして、良い主よ、CDATAの使用を考えさえしないでください。

XSLTのように考えて、「どの入力要素を出力要素に変換したいのか」と尋ねるだけです。

ulそれぞれにNが含まれていると仮定すると、最初のitem入力から始めて、N番目ごとの入力を:に変換する必要があります。itemul

<xsl:variable name="n" select="number(4)"/>

<xsl:template match="/">
  <output>
    <xsl:apply-templates select="/root/item[position() mod $n = 1]"/>
  </output>
</xsl:template>

これらの各item要素ulは、アイテムとそれに続くN-1個の兄弟のそれぞれを含むになります。

<xsl:template match="item">
  <ul>
    <xsl:for-each select=". | following-sibling::item[position() &lt; $n]">
      <li>
        <xsl:value-of select="."/>
      </li>
    </xsl:for-each>
  </ul>
</xsl:template>

次のような入力ドキュメントを想定します。

<root>
  <item>1</item>
  <item>2</item>
  <item>3</item>
  <item>4</item>
  <item>5</item>
  <item>6</item>
  <item>7</item>
  <item>8</item>
  <item>9</item>
</root>

$n...が4に設定されている場合、この出力が得られます。

<output>
  <ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
  </ul>
  <ul>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
  </ul>
  <ul>
    <li>9</li>
  </ul>
</output>
于 2009-10-09T02:20:31.970 に答える
1

再帰的なソリューションを使用してそれを行うことができます:

<xsl:call-template name="group">
  <xsl:with-param name="items" select="$myroot/item" />
</xsl:call-template>

<xsl:template name="group">
  <xsl:param name="items" />
  <xsl:if test="count($items) > 0">
    <ul>
      <xsl:for-each select="$items[position() &lt;= 3]">
        <li>...</li>
      </xsl:for-each>
    </ul>
    <xsl:call-template name="group">
      <xsl:with-param name="items" select="$items[position() > 3]" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>

groupこれが行うことは、アイテムのリスト全体のテンプレートを呼び出すことです。テンプレートは、リストのgroup最初の 3 つの要素 (3 つでない場合はそれ以下) を<ul> ... </ul>タグ内に書き出します。次に、最初の 3 つを省略したリストの残りの部分を使用して、再び自分自身を呼び出します。リストが空の場合、groupテンプレートは何もしません。

XSLT は非常に機能的な言語であり、ルールに従う (つまりdisable-output-escaping、これを使用しない) ことで、将来テンプレートを再度変更する必要が生じたときに、多くの苦痛や苦しみから解放されます。

于 2009-10-08T21:38:22.657 に答える
0

このようなことを試すことができます(テストされていませんが、アイデアはあります)

(...)
<xsl:call-template name="recursive">
 <xsl:with-param name="root" select="$myroot"/>
 <xsl:with-param name="index" select="number(1)"/>
</xsl:call-template>
(...)


<xsl:template name="recursive">
<xsl:param name="root"/>
<xsl:param name="index"/>
<ul>
<li><xsl:value-of select="$root/item[$index]"/></li>
<li><xsl:value-of select="$root/item[$index +1 ]"/></li>
</ul>
<xsl:if test="$root/item[$index+2]">
<xsl:call-template name="recursive">
 <xsl:with-param name="root" select="$root"/>
 <xsl:with-param name="index" select="$index+2"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
于 2009-10-08T21:37:22.500 に答える
-1

できるよ

<xsl:text disable-output-escaping="yes"><![CDATA[</ul>]]></xsl:text>

<xsl:text disable-output-escaping="yes"><![CDATA[<ul>]]></xsl:text>

だからあなたの場合:

<ul>
    <xsl:for-each select="$myroot/item">
        <li></li>

        <xsl:if test="position() mod $maxItemsPerColumn = 0">
            <xsl:text disable-output-escaping="yes"><![CDATA[</ul>]]></xsl:text>
            <xsl:text disable-output-escaping="yes"><![CDATA[<ul>]]></xsl:text>                
        </xsl:if>
    </xsl:for-each>
</ul>

更新: PierreとGregの回答を読んだ後、これを削除しましたが、あなたの質問に答えてくれるので、どこかで誰かに役立つ可能性があるので、これを維持することにしました。

更新2:ええ、なぜこれが恐ろしく、仲間のナズグルのような恐怖を刺激するのか理解しています。はい、私はこれを自分で反対票を投じようとしましたが、この答えは将来誰かに役立つかもしれないと思います。

于 2009-10-08T21:28:50.947 に答える