Решение этой проблемы - очень короткое и простое преобразование (абсолютно нет функции расширения требуются!):
<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>
<ul>
<xsl:apply-templates
select="document(entry)/*/tag">
<xsl:sort/>
</xsl:apply-templates>
</ul>
</html>
</xsl:template>
<xsl:template match="tag">
<li><xsl:value-of select="."/></li>
</xsl:template>
</xsl:stylesheet>
когда это преобразование применяется к предоставленному index.xml файлу :
<list>
<entry>a.xml</entry>
<entry>b.xml</entry>
</list>
желаемый, правильный результат получается :
<html>
<ul>
<li>aa</li>
<li>bb</li>
<li>cc</li>
<li>xx</li>
</ul>
</html>
и отображается в любом браузере как :
Пояснение : В этом решении используется мощность стандартной функции XSLT document()
. Как определено в Рекомендации W3C XSLT 1.0:
Когда функция документа имеет ровно один аргумент и аргумент
является набором узлов, то результатом является объединение для каждого узла в
набор параметров аргумента результата вызова функции документа с
первый аргумент является строковым значением узла
Это объясняет эффект этого фрагмента из нашего кода :
<xsl:apply-templates
select="document(entry)/*/tag">
<xsl:sort/>
</xsl:apply-templates>
Здесь происходит то, что аргумент функции document()
является набором узлов всех entry
дочерних элементов верхнего элемента index.xml
. Результатом является объединение всех узлов документа.
Поэтому
select="document(entry)/*/tag"
выделяет все элементы tag
во всех документах, на которые есть ссылка в index.xml
. Затем они сортируются (xsl:sort
), и каждый элемент уже отсортированного нодлиста обрабатывается шаблоном, соответствующим tag
.