Сделать документ результата XSLT обработанным "родительским" документом XSLT, рекурсивно
У меня есть документ grandchild.xml, чей результат после обработки с помощью granchild.xsl должен быть перенаправлен в child.xsl, затем он должен быть окончательно обработан и выведен parent.xsl.
Я пытался добавить xml-stylesheet
элемент к итоговому документу, ожидая, что он будет обработан с использованием указанной таблицы стилей XSL, но ничего не произошло.
Как правильно декларировать для выполнения этой задачи? Я много искал в интернете, но безрезультатно.
2 ответа
Если никто не знает лучше, я считаю, что возможность рекурсивной обработки вывода XSLT в браузере невозможна.
Чтобы доказать это, я только что попробовал следующее в IE8, FF14 и Chrome...
level1.xml
<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet title="XSL_formatting" type="text/xsl" href="level1.xsl"?>
<data>
<id>Level 1 data</id>
</data>
level1.xsl
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<?xml-stylesheet title="XSL_formatting" type="text/xsl" href="level2.xsl"?>
<data2>
<id2>Level 2: <xsl:value-of select="/data/id"/></id2>
</data2>
</xsl:template>
</xsl:stylesheet>
level2.xsl
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<b>Level 3:</b> <xsl:value-of select="/data2/id2"/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Результат от всех 3 браузеров просто для отображения Level 2: Level 1 Data
,
Вот пример многопроходного преобразования в браузере:
Давайте иметь этот исходный документ XML:
<?xml-stylesheet title="XSL_formatting"
type="text/xsl" href="MultiPassBrowser.xsl"?>
<nums>
<num>01</num>
<num>02</num>
<num>03</num>
<num>04</num>
<num>05</num>
<num>06</num>
<num>07</num>
<num>08</num>
<num>09</num>
<num>10</num>
</nums>
Давайте получим эти два XSLT-преобразования:
MultiPassBrowser1.xsl
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="num/text()">
<xsl:value-of select=". *2"/>
</xsl:template>
</xsl:stylesheet>
а также
MultiPassBrowser2.xsl
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*" mode="pass2">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="pass2"/>
</xsl:copy>
</xsl:template>
<xsl:template match="num" mode="pass2">
<p><xsl:value-of select=". +1"/></p>
</xsl:template>
</xsl:stylesheet>
Первое преобразование копирует XML-документ "как есть", но со строковым значением каждого num
элемент, умноженный на 2.
Второе преобразование копирует XML-документ "как есть", но со строковым значением каждого num
Элемент увеличен.
Если второе преобразование применяется к результату первого, конечные значения, полученные из начального num
элементы должны быть 3, 5, 7, ..., 21.
Вот преобразование, которое склеивает эти два:
MultiPassBrowser.xsl
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
exclude-result-prefixes="ext msxsl">
<xsl:import href="file:///C:/Temp/delete/MultiPassBrowser1.xsl"/>
<xsl:import href="file:///C:/Temp/delete/MultiPassBrowser2.xsl"/>
<xsl:output method="html"/>
<xsl:strip-space elements="*"/>
<msxsl:script language="JScript" implements-prefix="ext">
this['node-set'] = function (x) {
return x;
}
</msxsl:script>
<xsl:template match="/">
<html>
<xsl:variable name="vrtfPass1">
<xsl:apply-templates select="/*"/>
</xsl:variable>
<xsl:apply-templates select="ext:node-set($vrtfPass1)/*/*"
mode="pass2"/>
</html>
</xsl:template>
</xsl:stylesheet>
Результат, когда файл XML открывается с помощью IE, Firefox, Safari и Opera, является правильным, ожидаемым:
<html>
<p>3</p>
<p>5</p>
<p>7</p>
<p>9</p>
<p>11</p>
<p>13</p>
<p>15</p>
<p>17</p>
<p>19</p>
<p>21</p>
</html>
Пояснение:
Основной модуль таблицы стилей (тот, на который ссылается XML-документ PI) импортирует два модуля таблицы стилей, которые содержат отдельные преобразования.
Результат первого преобразования фиксируется в переменной
$vrtfPass1
,В XSLT 1.0 такая переменная имеет печально известный тип "RTF" (Result Tree Fragment) и не может работать напрямую (только копирование и
string()
функция может быть использована на RTF). Здесь мы используем портативный вариантxxx:node-set()
функция расширения, которая работает как в IE, так и в других четырех основных браузерах. Это портативное расширение было впервые предложено @DavidCarlisle, а оригинал можно найти в его блоге.Шаблоны в режиме "pass2" затем применяются к набору узлов, в который мы преобразовали на шаге выше переменную RTF. Все шаблоны во втором импортированном модуле таблиц стилей находятся в режиме "pass2", поэтому они выбраны для выполнения.
Окончательный результат получается.