Как применить параметр к атрибуту 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>