Сортировка с помощью XSLT - PullRequest
       16

Сортировка с помощью XSLT

5 голосов
/ 13 января 2011

ОБНОВЛЕНИЕ - Новый код внизу

Я пытаюсь выяснить, как использовать функцию сортировки для извлечения самой последней записи из некоторых данных XML.Я очень плохо знаком с использованием XSLT и сталкиваюсь с кучей проблем.Вот пример моих данных ...

<content date="1/13/2011 1:21:00 PM">
    <collection vo="promotion">
        <data vo="promotion" promotionid="64526" code="101P031" startdate="1/7/2011 12:00:00 AM"/>
        <data vo="promotion" promotionid="64646" code="101P046" startdate="1/9/2011 12:00:00 AM"/>
    </collection>
</content>

Я хочу отсортировать данные по promoid в порядке убывания, а затем ТОЛЬКО вывести через HTML наибольшее значение promoid.Вот то, что я пытался

ОБНОВЛЕНИЕ - Это последняя версия кода, которая все еще испытывает проблемы.

<html><body>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html"  encoding="UTF-8" />
    <xsl:template match="content/collection/data">
        <xsl:apply-templates>
            <xsl:sort select="promotionid" order="descending" data-type="number" />
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="content/collection">
        <xsl:value-of select="data/@promotionid" />
    </xsl:template> 
</xsl:stylesheet>
</body></html>

Хотя это и делаетвозвращать результаты я получаю «64526», а НЕ «64646».

Кто-нибудь может помочь?Также я видел примеры онлайн, где вы можете сортировать по нескольким полям.Возможно, стоит отметить сейчас, а не спрашивать позже, что мы можем захотеть закончить сортировку по дате начала, а не по рекламе.Мне удалось придумать код для разбивки даты по YYYY, MM и DD, но я понятия не имею, как бы я начал использовать это, кроме как использовать их в качестве моего параметра выбора типа, но я незнаю, работает ли это на самом деле или нет.

Year
<xsl:value-of select="substring(substring-after(substring-after(data/@startdate,'/'),'/'),1,4)" />

Month
<xsl:value-of select="substring-before(data/@startdate,'/')" />

Day
<xsl:value-of select="substring-before(substring-after(data/@startdate,'/'),'/')" />

Заранее благодарю и извиняюсь за свои менее чем начинающие навыки XSLT.

------------------------------------------------------

После некоторой помощи здесь код изменился, но все еще не работает, как предполагалось.Вот код ...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html"  encoding="UTF-8" />
    <xsl:template match="content/collection/">
            <xsl:apply-templates>
                <xsl:sort select="@promotionid" order="descending" data-type="number" />
            </xsl:apply-templates>
        </xsl:template>

 <xsl:template match="content/collection/data">
        <xsl:if test="position()=1">
                   <xsl:value-of select="@promotionid"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

И я по-прежнему вижу меньшее значение выхода, чем большее.Возможно, есть другой способ сделать это без сортировки?Поскольку я также открыт для этой возможности.

1/14/11 10:37 Обновление * ------------------------------------------------------------------ * Хорошо, использование этого кода теперь действительно сортирует данные и выдает наибольший рекламный номер.Спасибо за тонну!

<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="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="collection">
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="data">
         <xsl:sort select="@promotionid" data-type="number" order="descending"/>
        </xsl:apply-templates>
      </xsl:copy>
    </xsl:template>
<xsl:template match="content/collection/data">
        <xsl:if test="position()=1">
                   <xsl:value-of select="@promotionid"/>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

Не обращая внимания на promtionid, теперь вы можете показать мне, как я сортировал бы по убыванию, ТОЛЬКО по дате?Я попытался удалить К сожалению, я знаю, что даты должны иметь статическую длину, но мы не можем контролировать данные, которые мы получаем: - (

Также вы можете порекомендовать книгу, с которой можно начать, чтобы действительно лучше понять всеэто? Вы оказали огромную помощь!

1 Ответ

5 голосов
/ 13 января 2011
<xsl:sort select="promotionid" order="descending" data-type="number"

/>

Здесь есть очевидная ошибка : promotionid - это атрибут, а не элемент.

Решение

select="@promotionid" order="descending" data-type="number" />

Другая ошибка :

<xsl:template match="content/collection/data">
    <xsl:apply-templates>
        <xsl:sort select="promotionid" order="descending" data-type="number" />
    </xsl:apply-templates>
</xsl:template>

<xsl:apply-templates> и сортировка выполняется слишком поздно.

Вы хотите :

<xsl:template match="content/collection/">
            <xsl:apply-templates>
                <xsl:sort select="@promotionid" order="descending" data-type="number" />
            </xsl:apply-templates>
        </xsl:template>

и

    <xsl:template match="content/collection/data">
        <xsl:if test="position()=1">
                   <xsl:value-of select="@promotionid"/>
        </xsl:if>
    </xsl:template>

Что касается расширенного вопроса :

Это преобразование:

<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="node()|@*">
      <xsl:copy>
         <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="collection">
      <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="data">
         <xsl:sort select="@promotionid" data-type="number" order="descending"/>
         <xsl:sort select=
          "concat(
             substring-after(substring-after(substring-before(@startdate,' ')
                                             ,'/'
                                             ),
                               '/'
                               ),
             substring-before(substring-after(substring-before(@startdate,' ')
                                             ,'/'
                                             ),
                              '/'
                            ),
             substring-before(substring-after(substring-before(@startdate,' ')
                                             ,'/'
                                             ),
                               '/'
                               )
                )"/>
        </xsl:apply-templates>
      </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

применительно к предоставленному документу XML :

<content date="1/13/2011 1:21:00 PM">
    <collection vo="promotion">
        <data vo="promotion" promotionid="64526" code="101P031" startdate="1/7/2011 12:00:00 AM"/>
        <data vo="promotion" promotionid="64646" code="101P046" startdate="1/9/2011 12:00:00 AM"/>
    </collection>
</content>

дает желаемый результат :

<content date="1/13/2011 1:21:00 PM">

   <collection vo="promotion">
      <data vo="promotion" promotionid="64646" code="101P046" startdate="1/9/2011 12:00:00 AM"/>
      <data vo="promotion" promotionid="64526" code="101P031" startdate="1/7/2011 12:00:00 AM"/>
   </collection>

</content>

Однако, обратите внимание , что это не обрабатывает переменную длину для компонентов даты. Лучше использовать формат фиксированной длины: мм / дд / гггг

...