2010-05-17 6 views
2

Я хотел бы, чтобы список отсортировался, игнорируя любые исходные определенные/неопределенные статьи «the» и «a». Например:Игнорирование «A» и «The» при сортировке с XSLT

  • Комедия ошибок
  • Гамлет
  • Сон в летнюю ночь
  • Двенадцатая ночь
  • Зимняя сказка

Я думаю, что, возможно, в XSLT 2.0 это может быть достигнутых в рамках:

<xsl:template match="/"> 
    <xsl:for-each select="play"/> 
    <xsl:sort select="if (starts-with(title, 'A ')) then substring(title, 2) else 
         if (starts-with(title, 'The ')) then substring(title, 4) else title"/> 
    <p><xsl:value-of select="title"/></p> 
    </xsl:for-each> 
</xsl:template> 

Однако я хочу использовать обработку в браузере, поэтому вам нужно использовать XSLT 1.0. Есть ли способ достичь этого в XLST 1.0?

+4

Обычно правильный подход для этого является сохранить «сортировку заголовок» для каждого элемента, так как правила могут стать очень сложно и даже распространяться на другие языки (например, «Die» - это статья, и ее следует игнорировать на немецком языке, но «Die Hard» не следует сортировать под «H», даже если она найдена в индексе на немецком языке). Название вида «Сон в летнюю ночь» будет «Сон в летнюю ночь». –

+0

Я должен был упомянуть, start-with() доступен в XLST 1.0, но if-then-else не ... – ChrisV

+0

@Joachim - вы правы, но мне нужно работать с существующими данными, нет никакого ресурса для поддерживать параллельное поле сортировки; Gart's quick-n-грязное решение - это то, что мне нужно - хороший комментарий, хотя – ChrisV

ответ

4

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

<xsl:template match="plays"> 
<p>Plays sorted by title: </p> 
    <xsl:for-each select="play"> 
     <xsl:sort select= 
     "concat(@title 
       [not(starts-with(.,'A ') 
        or 
        starts-with(.,'The '))], 
       substring-after(@title[starts-with(., 'The ')], 'The '), 
       substring-after(@title[starts-with(., 'A ')], 'A ') 
      ) 
    "/> 
     <p> 
     <xsl:value-of select="@title"/> 
     </p> 
    </xsl:for-each> 
</xsl:template> 

при нанесении на этом XML-документ:

производит разыскиваемый, правильный результат:

<p>Plays sorted by title: </p> 
<p>Barber</p> 
<p>The Comedy of Errors</p> 
<p>CTA &amp; Fred</p> 
<p>Hamlet</p> 
<p>A Midsummer Night's Dream</p> 
<p>Twelfth Night</p> 
<p>The Winter's Tale</p> 
+0

Второе отличное решение, Dimitre, которое позволяет избежать математики решения Gart - спасибо также! Так как мне пришлось подумать об этом чуть больше, я добавлю для других выгоду: например, для «Зимней сказки» ценность, которую он будет сортировать, будет «Зимняя сказка« Зимняя сказка ». – ChrisV

+0

@ChrisV: Да, преимущество этого решения в том, что оно проще и дает меньше шансов совершить ошибки при выполнении арифметики. Независимо от того, что ключи сортировки кажутся странными, это не влияет на значения, которые окончательно выводятся. –

+0

Могут возникнуть проблемы, если «The» - это середина текста, более похожее на «... Something The Something ..» (извините, не могу представить ни одного реального примера). Кроме того, в общем случае следует также рассматривать статью «An». – Gart

2

Вот как я бы это сделать:

<xsl:template match="plays"> 
    <xsl:for-each select="play"> 
     <xsl:sort select="substring(title, 1 + 2*starts-with(title, 'A ') + 4*starts-with(title, 'The '))"/> 
     <p> 
     <xsl:value-of select="title"/> 
     </p> 
    </xsl:for-each> 
</xsl:template> 

Update: Я забыл добавить 1 к выражению (классический ошибка на единицу)

Ну, starts-with от XSLT 1.0. Prooflink: первый результат поиска в Google дает XSLT 1.0: function starts-with

+0

Проблема в том, что 'start-with' является XSLT 2.0, я думаю - * Редактировать * Я стою исправлен! – Phil

+1

Я исправил себя, как только я ударил сообщение 23 минуты назад, я просто не хотел удалять исходный комментарий, потому что кажется подозрительным удалить свои собственные ошибки. Приветствия. – Phil

+0

Отличное простое, креативное решение Gart - Спасибо! – ChrisV

Смежные вопросы