Лучший подход для объединения нескольких проходов XSLT 1.0, которые обрабатывают одни и те же узлы
Я делаю очень сложное преобразование XSLT 1.0 (в настоящее время использую 8 проходов XSLT). Я хочу объединить эти 8 проходов без объединения их в один файл (это было бы слишком сложно). Мое решение будет использовать xsl:include
а также exsl:node-set
объединить проходы и сохранить временные результаты в переменных.
Но у меня есть одна проблема: мое преобразование передает копии большинства узлов и изменяет только определенные аспекты. Поэтому мне нужно обрабатывать одни и те же узлы на каждом проходе, но с разными xsl:template
! Но как мне это сделать? Как сказать, что после первого прохода я хочу применить шаблоны из других таблиц стилей XSLT?
Очень упрощенный пример того, что я сейчас делаю (2 прохода XSLT):
Источник:
<h>something here</h>
После XSLT пройти 1:
<h someattribute="1">something here</h>
После XSLT пройти 2:
<h someattribute="1" somemoreattribute="2">something here, and even more</h>
Мой текущий подход состоит в том, чтобы дважды вызвать процессор XSLT и временно сохранить результаты на диске:
xsltproc stylesheet1.xsl input.xml >temp.xml
xsltproc stylesheet2.xsl temp.xml >finalresult.xml
2 ответа
Одним из возможных решений было бы изменить каждую из таблиц стилей для использования отдельного режима. Затем вы можете импортировать их все в основную таблицу стилей и сделать несколько проходов, применяя шаблоны по очереди в каждом режиме:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl"
version="1.0">
<xsl:import href="stylesheet1.xsl"/> <!-- assuming mode="stylesheet1" -->
<xsl:import href="stylesheet2.xsl"/> <!-- assuming mode="stylesheet2" -->
<xsl:import href="stylesheet3.xsl"/> <!-- assuming mode="stylesheet3" -->
<xsl:template match="/">
<xsl:variable name="temp1">
<xsl:apply-templates select="." mode="stylesheet1"/>
</xsl:variable>
<xsl:variable name="temp2">
<xsl:apply-templates mode="stylesheet2" select="exsl:node-set($temp1)"/>
</xsl:variable>
<xsl:apply-templates mode="stylesheet3" select="exsl:node-set($temp2)"/>
</xsl:template>
</xsl:stylesheet>
Недостатком является то, что вам нужно изменить оригинальные таблицы стилей, добавив соответствующие mode
атрибуты для каждого xsl:template
а также xsl:apply-templates
, Вы все еще можете заставить таблицы стилей работать независимо друг от друга, добавив в каждый из них дополнительный шаблон:
<xsl:template match="/">
<xsl:apply-templates select="." mode="stylesheet1"/>
</xsl:template>
Почему бы не использовать
<xsl:param name="iteration"/>
И передать номер итерации в таблицу стилей? Затем вы можете использовать это так
<xsl:if test="$iteration = 1">
...
</xsl:if>
... или в других контекстах
Вы можете установить параметр с
javax.xml.transform.Transformer.setParameter("iteration", 1);
Или с муравьем:
<xslt ...>
<param name="iteration" expression="1"/>
</xslt>