将模板应用于相邻元素?

时间:2013-01-31 16:38:00

标签: .net xslt xslt-1.0

给出如下输入:

<p>Some information about the proceeding source listing:</p>
<code language="CSharp"><![CDATA[ ... ]]></code>
<code language="AnotherLanguage"><![CDATA[ ... ]]></code>

<p>This is a different example which perhaps applies to just one language:</p>
<code language="CSharp"><![CDATA[ ... ]]></code>

<p>Another example:</p>
<code language="CSharp"><![CDATA[ ... ]]></code>
<code language="AnotherLanguage"><![CDATA[ ... ]]></code>
<code language="YetAnotherLanguage"><![CDATA[ ... ]]></code>

使用XSLT 1.0,如何对相邻的<code>元素进行分组,如下所示:

<p>Some information about the proceeding source listing:</p>
<div class="source-selector">
    <ul class="tabs">
        <li class="tab" data-language="CSharp">CSharp</li>
        <li class="tab" data-language="AnotherLanguage">AnotherLanguage</li>
    </ul>
    <div data-language="CSharp">
        <pre>...</pre>
    </div>
    <div data-language="AnotherLanguage">
        <pre>...</pre>
    </div>
</div>

<p>This is a different example which perhaps applies to just one language:</p>
<div class="source-selector">
    <ul class="tabs">
        <li class="tab" data-language="CSharp">CSharp</li>
    </ul>
    <div data-language="CSharp">
        <pre>...</pre>
    </div>
</div>

<p>Another example:</p>
<div class="source-selector">
    <ul class="tabs">
        <li class="tab" data-language="CSharp">CSharp</li>
        <li class="tab" data-language="AnotherLanguage">AnotherLanguage</li>
        <li class="tab" data-language="YetAnotherLanguage">YetAnotherLanguage</li>
    </ul>
    <div data-language="CSharp">
        <pre>...</pre>
    </div>
    <div data-language="AnotherLanguage">
        <pre>...</pre>
    </div>
    <div data-language="YetAnotherLanguage">
        <pre>...</pre>
    </div>
</div>

这就是我目前无法正常工作的原因,因为所有其他内容(如本例中的段落)后所有源代码都被分组到一个单一选择器中。

<!-- Display paragraphs first -->
<xsl:apply-templates select="*[not(name() = 'code')]"/>

<!-- Display consecutive source code within selector -->
<div class="source-selector">
    <ul class="tabs">
    <xsl:for-each select="code">
        <li class="tab" data-language="{@language}"><include item="{@language}Label"/></li>
    </xsl:for-each>
    </ul>
<xsl:for-each select="code">
    <div data-language="{@language}">
        <pre><xsl:copy-of select="node()"/></pre>
    </div>
</xsl:for-each>
</div>

1 个答案:

答案 0 :(得分:1)

您可以在XSLT 1.0中通过让模板一次跳到元素的下一个邻居来完成此操作,如下所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/*">
    <div>
      <xsl:apply-templates select="*[not(self::code)]" />
    </div>
  </xsl:template>

  <xsl:template match="/*/*[not(self::code)]">
    <xsl:copy-of select="."/>
    <!-- Select the next neighbor element, but only if it is a <code> -->
    <xsl:variable name="firstCode" select="following-sibling::*[1][self::code]" />
    <div class="source-selector">
      <!-- Skip the part with the <ul> if there are no <code> neighbors-->
      <xsl:if test="$firstCode">
        <ul>
          <xsl:apply-templates select="$firstCode" mode="list" />
        </ul>
        <xsl:apply-templates select="$firstCode" mode="samples" />
      </xsl:if>
    </div>
  </xsl:template>

  <xsl:template match="code" mode="list">
    <li class="tab" data-language="{@language}">
      <xsl:value-of select="@language"/>
    </li>
    <!-- Apply this template to the next neighbor, if it is a <code> -->
    <xsl:apply-templates select="following-sibling::*[1][self::code]" mode="list" />
  </xsl:template>

  <xsl:template match="code" mode="samples">
    <div data-language="{@language}">
      <pre>
        <xsl:value-of select="string(.)"/>
      </pre>
    </div>
    <!-- Apply this template to the next neighbor, if it is a <code> -->
    <xsl:apply-templates 
                       select="following-sibling::*[1][self::code]" mode="samples" />
  </xsl:template>

</xsl:stylesheet>

在样本输入上运行时,会产生:

<div>
  <p>Some information about the proceeding source listing:</p>
  <div class="source-selector">
    <ul>
      <li class="tab" data-language="CSharp">CSharp</li>
      <li class="tab" data-language="AnotherLanguage">AnotherLanguage</li>
    </ul>
    <div data-language="CSharp">
      <pre> ... </pre>
    </div>
    <div data-language="AnotherLanguage">
      <pre> ... </pre>
    </div>
  </div>
  <p>This is a different example which perhaps applies to just one language:</p>
  <div class="source-selector">
    <ul>
      <li class="tab" data-language="CSharp">CSharp</li>
    </ul>
    <div data-language="CSharp">
      <pre> ... </pre>
    </div>
  </div>
  <p>Another example:</p>
  <div class="source-selector">
    <ul>
      <li class="tab" data-language="CSharp">CSharp</li>
      <li class="tab" data-language="AnotherLanguage">AnotherLanguage</li>
      <li class="tab" data-language="YetAnotherLanguage">YetAnotherLanguage</li>
    </ul>
    <div data-language="CSharp">
      <pre> ... </pre>
    </div>
    <div data-language="AnotherLanguage">
      <pre> ... </pre>
    </div>
    <div data-language="YetAnotherLanguage">
      <pre> ... </pre>
    </div>
  </div>
</div>