XSLT: использовать параметры в атрибутах xls: sort (динамическая сортировка) - PullRequest
1 голос
/ 27 марта 2010

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

1 Ответ

9 голосов
/ 27 марта 2010

Вы близки к правильному решению , но есть несколько проблем:

  1. <xsl:param name="sortBy" select="viewCount"/> Это определяет параметр $sortBy как значение дочернего элемента viewCount текущего узла (узла документа). Поскольку верхний элемент не называется viewCount, определенный таким образом параметр $sortBy не имеет значения вообще.

  2. <xsl:param name="order" select="descending"/> То же самое.

  3. <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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...