XSLT 1.0 добавляет один тип данных к четырем (строка, число, логическое значение, набор узлов), включенных в модель данных XPath 1.0: фрагменты дерева результатов (https://www.w3.org/TR/xslt-10/#section-Result-Tree-Fragments):
Это дополнительноетип данных называется фрагментом результирующего дерева. Переменная может быть связана с фрагментом результирующего дерева вместо одного из четырех основных типов данных XPath (строка, число, логическое значение, набор узлов). Фрагмент результирующего дерева представляет собой фрагментрезультирующее дерево. Фрагмент результирующего дерева обрабатывается эквивалентно набору узлов, который содержит только один корневой узел. Однако операции, разрешенные для фрагмента результирующего дерева, являются подмножеством операций, разрешенных для набора узлов.фрагмент результирующего дерева, только если эта операция будет разрешена для строки (операция со строкой может включать в себя сначала преобразование строки в число или логическое значение). В частности, нельзя использовать /
, //
и []
операторы на фрагментах дерева результатов.
Таким образом, вы можете иметь посредникаy приводит к фрагментам результирующего дерева, но если вы собираетесь использовать что-то большее, чем xsl:copy-of
или xsl:value-of
или принимать строковое значение, вам нужно выйти за пределы XSLT 1.0, и в большинстве процессоров XSLT 1.0 у вас есть поддержка такой функции расширения, как exsl:node-set
для этого он преобразует фрагмент результирующего дерева в набор узлов.
Вот простой пример, который сначала обрабатывает некоторые элементы из входных данных, чтобы добавить атрибут, и преобразует этот результирующий фрагмент дерева в узел-установите с помощью exsl:node-set
(http://exslt.org/exsl/functions/node-set/index.html), чтобы затем использовать этот набор узлов дважды для двух разных режимов:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
xmlns:msxml="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="exsl msxml"
version="1.0">
<xsl:output method="html" indent="yes" version="5" doctype-system="about:legacy-doctype"/>
<xsl:variable name="numbered-items-rtf">
<xsl:apply-templates select="//item" mode="number"/>
</xsl:variable>
<xsl:variable name="numbered-items" select="exsl:node-set($numbered-items-rtf)/item"/>
<xsl:template match="item" mode="number">
<xsl:copy>
<xsl:attribute name="index">
<xsl:number/>
</xsl:attribute>
<xsl:copy-of select="node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<html>
<head>
<title>.NET XSLT Fiddle Example</title>
<style>
nav ul li { display: inline }
nav ul { list-item-type: none }
</style>
</head>
<body>
<h1>Example</h1>
<nav>
<ul>
<xsl:apply-templates select="$numbered-items" mode="nav"/>
</ul>
</nav>
<section>
<h2>List</h2>
<ul>
<xsl:apply-templates select="$numbered-items"/>
</ul>
</section>
</body>
</html>
</xsl:template>
<xsl:template match="item">
<li id="item-{@index}">
<xsl:apply-templates/>
</li>
</xsl:template>
<xsl:template match="item" mode="nav">
<li>
<a href="#item-{@index}">
<xsl:apply-templates/>
</a>
</li>
</xsl:template>
</xsl:stylesheet>
Пример ввода, такой как
<root>
<items>
<item>foo</item>
<item>bar</item>
<item>baz</item>
</items>
</root>
, преобразуется в
<!DOCTYPE html SYSTEM "about:legacy-doctype">
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-16">
<title>.NET XSLT Fiddle Example</title>
<style>
nav ul li { display: inline }
nav ul { list-item-type: none }
</style>
</head>
<body>
<h1>Example</h1><nav><ul>
<li><a href="#item-1">foo</a></li>
<li><a href="#item-2">bar</a></li>
<li><a href="#item-3">baz</a></li>
</ul></nav><section><h2>List</h2>
<ul>
<li id="item-1">foo</li>
<li id="item-2">bar</li>
<li id="item-3">baz</li>
</ul></section></body>
</html>
https://xsltfiddle.liberty -development.net / pPqsHUd / 1
Недостатком является то, что некоторые процессоры XSLT 1.0 не поддерживают функцию exsl:node-set
но аналогичное в проприетарном пространстве имен (например, процессоры MSXML (3,4,5,6) от Microsoft на базе COM поддерживают только msxml:node-set
в пространстве имен xmlns:msxml="urn:schemas-microsoft-com:xslt"
, как это делает (устаревшая) основанная на .NET XslTransform
).Пока вы нацелены на один процессор XSLT 1.0, вы, конечно, можете адаптировать свой код для использования правильной функции пространства имен / расширения, но если вы хотите ориентироваться на разные, вам будет сложно найти компактный и элегантный способ использования различных функций расширения на основеfunction-available
поскольку у вас нет выражения if
в XPath 1.0.
So https://xsltfiddle.liberty -development.net / pPqsHUd / 2 работает, например, с Chrome и браузерами Mozillaкак Firefox, так как эти браузеры поддерживают exsl:node-set
, но не работают в Microsoft IE и Edge, поскольку они используют MSXML и не поддерживают exsl:node-set
, для них вам нужно <xsl:variable name="numbered-items" select="msxml:node-set($numbered-items-rtf)/item"/>
, как в https://xsltfiddle.liberty -development.net/pPqsHUd/3.
В IE вы можете использовать расширение скрипта для поддержки exsl:node-set
, но, к сожалению, в Edge это не работает: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7598626/.