给定如下输入:
<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>
在 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>