У меня есть ситуация, где цикл через отсортированный набор узлов и применяет шаблон на каждый из узлов:
<div id="contractscontainer">
<xsl:for-each select="document">
<xsl:sort select="content[@name='ClientName']/text()" />
<xsl:apply-templates select="." mode="client-contract" />
</xsl:for-each>
</div>
Я хочу сделать что-то специальное с "первыми" 5 узлами в наборе узлов и представить их вложенный элемент. Проблема состоит в том, что они должны быть в том же порядке, как будто они были отсортированы (поскольку они в курсе).
Я запланировал выполнение этого при помощи два xsl:for-each
элементы, каждый с корректными узлами, выбранными из набора. Я не могу сделать этого, однако, потому что они должны быть отсортированы, прежде чем я смогу выбрать "первые" 5.
Пример:
<div id="contractscontainer">
<div class="first-five">
<xsl:for-each select="document[position() < 6]">
<xsl:sort select="content[@name='ClientName']/text()" />
<xsl:apply-templates select="." mode="client-contract" />
</xsl:for-each>
</div>
<div class="rest-of-them">
<xsl:for-each select="document[position() > 5]">
<xsl:sort select="content[@name='ClientName']/text()" />
<xsl:apply-templates select="." mode="client-contract" />
</xsl:for-each>
</div>
</div>
Я не думаю, что это будет работать, потому что я выбираю узлы положением прежде, чем отсортировать их, но я не могу использовать xsl:sort
за пределами xsl:for-each
.
Я приближаюсь к этому неправильно?
Править: Мое текущее решение состоит в том, чтобы отсортировать их и сохранить отсортированный набор в другой переменной:
<xsl:variable name="sorted-docs">
<xsl:for-each select="document">
<xsl:sort select="content[@name='ClientName']/text()" />
<xsl:copy-of select="." />
</xsl:for-each>
</xsl:variable>
Это работает, но является там лучшим путем?
Вот один из способов сделать это в XSLT 1.0 без необходимости использования функции расширения xxx: node-set () :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<html>
<div class="first-five">
<xsl:apply-templates select="num">
<xsl:sort select="." data-type="number"/>
<xsl:with-param name="pStart" select="1"/>
<xsl:with-param name="pEnd" select="5"/>
</xsl:apply-templates>
</div>
<div class="rest-of-them">
<xsl:apply-templates select="num">
<xsl:sort select="." data-type="number"/>
<xsl:with-param name="pStart" select="6"/>
</xsl:apply-templates>
</div>
</html>
</xsl:template>
<xsl:template match="num">
<xsl:param name="pStart"/>
<xsl:param name="pEnd" select="999999999999"/>
<xsl:if test="position() >= $pStart
and
not(position() > $pEnd)">
<p><xsl:value-of select="."/></p>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Когда вышеупомянутое преобразование применяется к этому простому XML-документу :
<nums>
<num>5</num>
<num>3</num>
<num>6</num>
<num>8</num>
<num>4</num>
<num>1</num>
<num>9</num>
<num>2</num>
<num>7</num>
<num>10</num>
</nums>
создается желаемый результат :
<html>
<div class="first-five">
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
</div>
<div class="rest-of-them">
<p>6</p>
<p>7</p>
<p>8</p>
<p>9</p>
<p>10</p>
</div>
</html>