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>
4

1 回答 1

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>
于 2013-01-31T16:54:24.943 回答