Сформулируйте по буквам два элемента в одном списке с помощью XSLT - PullRequest
1 голос
/ 31 августа 2011

Я очень плохо знаком с XSLT, поэтому, пожалуйста, потерпите меня, если мое кодирование небрежно или излишне сложно. Я пытаюсь создать список песен, которые, помимо прочего, должны быть в алфавитном порядке по названию. Для некоторых песен я перечислил названия на нескольких языках. Можно ли, например, всегда сортировать по алфавиту по-японски, но если его нет, то по алфавиту по английскому названию. Вот пример:

<music-catalogue>
    <song>
        <title>
            <romaji>Agechikuten</romaji>
            <japanese>&#25562;&#20316;&#30000;</japanese>
        </title>
    </song>
    <song>
        <title>
            <romaji>Kamigami no Uta</romaji>
            <japanese>&#31070;&#12293;&#12398;&#35433;</japanese>
            <english>Song of the Gods</english>
        </title>
        <artist>
            <e-name>Himekami</e-name>
            <j-name>&#23019;&#31070;</j-name>
            <link>&himekami;</link>
        </artist>
    </song>
    <song>
        <title>
            <english>Freedom</english>
        </title>
        <artist>
            <e-name>12 Girls Band</e-name>
            <j-name>&#22899;&#23376;&#21313;&#20108;&#20048;&#22346;</j-name>
        </artist>
    </song>
    <song>
        <title>
            <romaji>Tinsagu nu Hana</romaji>
            <japanese>&#12486;&#12451;&#12531;&#12469;&#12464;&#12396;&#33457;</japanese>
        </title>
    </song>
</music-catalogue>

В настоящее время песни отображаются по содержанию элемента ромадзи, который будет отображать:

  • Свобода
  • Agechikuten
  • Камигами но Ута
  • Tinsagu nu Hana

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

  • Agechikuten
  • Свобода
  • Камигами но Ута
  • Tinsagu nu Hana

Пожалуйста, дайте мне знать, если я должен включить больше информации или частей моего кодирования. Спасибо!

Ответы [ 3 ]

3 голосов
/ 31 августа 2011

Я думаю, что этого можно достичь с помощью элемента xsl: sort , который можно использовать как с xsl: for-each , так и с xsl: apply-templates

<xsl:sort select="concat(title/romaji, title[not(romaji)]/english)" />

Таким образом, это означает сортировку заголовка ромадзи, но если его нет, будет использован заголовок на английском языке.

Вот простой XSLT для демонстрации

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/music-catalogue">
      <ol>
         <xsl:apply-templates select="song">
            <xsl:sort select="concat(title/romaji, title[not(romaji)]/english)" />
         </xsl:apply-templates>
      </ol>
   </xsl:template>

   <xsl:template match="song">
      <li>
         <xsl:value-of select="concat(title/romaji, title[not(romaji)]/english)" />
      </li>
   </xsl:template>
</xsl:stylesheet>

При применении к вашему образцу XML выводятся следующие результаты

<ol>
   <li>Agechikuten</li>
   <li>Freedom</li>
   <li>Kamigami no Uta</li>
   <li>Tinsagu nu Hana</li>
</ol>
1 голос
/ 31 августа 2011

Это похоже на решение, предложенное @Tim C, но избавляет от необходимости использовать конкатенацию строк :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="/*">
     <xsl:apply-templates select="song/title">
       <xsl:sort select="romaji | self::*[not(romaji)]/english"/>
     </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="title">
  <xsl:text>&#xA;</xsl:text>
  <xsl:value-of select=
   "romaji | self::*[not(romaji)]/english"/>
 </xsl:template>
</xsl:stylesheet>

Применительно к предоставленному документу XML (слегка изменен, чтобы сделать его правильно сформированным - отредактировал неопределенную ссылку на сущность):

<music-catalogue>
    <song>
        <title>
            <romaji>Agechikuten</romaji>
            <japanese>&#25562;&#20316;&#30000;</japanese>
        </title>
    </song>
    <song>
        <title>
            <romaji>Kamigami no Uta</romaji>
            <japanese>&#31070;&#12293;&#12398;&#35433;</japanese>
            <english>Song of the Gods</english>
        </title>
        <artist>
            <e-name>Himekami</e-name>
            <j-name>&#23019;&#31070;</j-name>
            <link>&amp;himekami;</link>
        </artist>
    </song>
    <song>
        <title>
            <english>Freedom</english>
        </title>
        <artist>
            <e-name>12 Girls Band</e-name>
            <j-name>&#22899;&#23376;&#21313;&#20108;&#20048;&#22346;</j-name>
        </artist>
    </song>
    <song>
        <title>
            <romaji>Tinsagu nu Hana</romaji>
            <japanese>&#12486;&#12451;&#12531;&#12469;&#12464;&#12396;&#33457;</japanese>
        </title>
    </song>
</music-catalogue>

желаемый, правильный результат получается :

Agechikuten
Freedom
Kamigami no Uta
Tinsagu nu Hana

Объяснение

В этом решении искомый ключ сортировки выражается точно с помощью установленной арифметики:

 romaji | self::*[not(romaji)]/english

, где | - оператор XPath union .

Обратите внимание , что это решение работает правильно, даже если english предшествует (в порядке документа) romaji.

1 голос
/ 31 августа 2011

Обычный способ добиться такого рода сортировки - объединение искомых узлов:

<xsl:stylesheet  version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" /> 
        </xsl:copy>
    </xsl:template>

    <xsl:template match="music-catalogue">
        <xsl:copy>
            <xsl:apply-templates select="song">
                <xsl:sort select="title/romaji | title[not(romaji)]/english"/>
            </xsl:apply-templates>
        </xsl:copy> 
    </xsl:template>

</xsl:stylesheet>

производит:

<music-catalogue>
   <song>
      <title>
         <romaji>Agechikuten</romaji>
         <japanese>揚作田</japanese>
      </title>
   </song>
   <song>
      <title>
         <english>Freedom</english>
      </title>
      <artist>
         <e-name>12 Girls Band</e-name>
         <j-name>女子十二乐坊</j-name>
      </artist>
   </song>
   <song>
      <title>
         <romaji>Kamigami no Uta</romaji>
         <japanese>神々の詩</japanese>
         <english>Song of the Gods</english>
      </title>
      <artist>
         <e-name>Himekami</e-name>
         <j-name>姫神</j-name>
         <link/>
      </artist>
   </song>
   <song>
      <title>
         <romaji>Tinsagu nu Hana</romaji>
         <japanese>ティンサグぬ花</japanese>
      </title>
   </song>
</music-catalogue>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...