Как применить параметр к атрибуту select и order в элементе xsl:sort ? Мне хотелось бы сделать эту динамику с PHP с чем-то вроде этого:
$xsl = new XSLTProcessor(); $xslDoc = new DOMDocument(); $xslDoc->load( $this->_xslFilePath ); $xsl->importStyleSheet( $xslDoc ); $xsl->setParameter( '', 'sortBy', 'viewCount' ); $xsl->setParameter( '', 'order', 'descending' );
Но я сначала должен был понять, как заставить это работать. Я пробовал следующее, но он дает мне ошибку компиляции: «Недопустимое значение $ order for order». $sortBy ничего не делает:
<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:param name="sortBy" select="viewCount"/> <xsl:param name="order" select="descending"/> <xsl:template match="/"> <media> <xsl:for-each select="media/medium"> <xsl:sort select="$sortBy" order="$order"/> // <someoutput> </xsl:for-each> </media> </xsl:template> </xsl:stylesheet>
Вы близки к правильному решению , но есть несколько вопросов:
<xsl:param name="sortBy" select="viewCount"/> Это определяет параметр $sortBy как значение viewCount текущего узла (узла документа). Поскольку верхний элемент не называется viewCount , параметр $sortBy определенный таким образом, вообще не имеет значения.
<xsl:param name="order" select="descending"/> То же.
<xsl:sort select="$sortBy" order="$order"/> Даже если исправлены проблемы 1 и 2., эта инструкция xslt все еще проблематична. Он определяет значение атрибута order как буквенную строку '$order' – не как значение параметра $order . Способ сделать это в XSLT – это использовать AVT (шаблон значения атрибута). Всякий раз, когда мы хотим указать, что внутри значения атрибута мы хотим, чтобы определенная строка была оценена как выражение XPath, эта строка должна быть окружена фигурными фигурными скобками.
Таким образом, атрибут order должен быть указан как: order = '{$order}' .
К сожалению, AVT не могут использоваться для атрибута select (другое правило из спецификации XSLT).
Способ задания значения атрибута select является немного более сложным:
select='*[name()=$sortBy]' Это говорит: сортировка по дочернему элементу, имя которого совпадает с значением переменной $sortBy .
Чтобы соединить все это, вот скорректированное преобразование :
<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:param name="sortBy" select="'viewCount'"/> <xsl:param name="order" select="'descending'"/> <xsl:template match="/"> <media> <xsl:for-each select="media/medium"> <xsl:sort select="*[name()=$sortBy]" order="{$order}"/> <xsl:copy-of select="."/> </xsl:for-each> </media> </xsl:template> </xsl:stylesheet>
Когда это преобразование применяется к следующему XML-документу :
<media> <medium> <viewCount>2</viewCount> </medium> <medium> <viewCount>1</viewCount> </medium> <medium> <viewCount>5</viewCount> </medium> </media>
Производится правильный результат :
<media> <medium> <viewCount>5</viewCount> </medium> <medium> <viewCount>2</viewCount> </medium> <medium> <viewCount>1</viewCount> </medium> </media>