2011-08-31 2 views
1

Я очень новичок в XSLT, поэтому, пожалуйста, несите меня, если мое кодирование небрежно или излишне сложно. Я пытаюсь создать список песен, которые, среди прочего, должны быть в алфавитном порядке по названию. Для некоторых из некоторых песен я перечислил названия на нескольких языках. Можно ли всегда сортировать по алфавиту по-японски, например, но если его нет, то алфавиту по английскому названию. Вот пример:Алфавит двух элементов в том же списке с 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
  • Kamigami нет Ута
  • Tinsagu ню Хана

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

  • Agechikuten
  • Свобода
  • Kamigami нет Ута
  • Tinsagu ню Hana

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

ответ

1

Это аналогично решению, предложенному 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 

где | is XPath union op Erator.

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

+0

Спасибо, это сработало отлично! –

+0

@ Лукас Шнайдер: Добро пожаловать –

3

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

<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> 
+0

Это довольно хороший трюк :-) 'concat (title/romaji, title [not (romaji)]/english)' – Chris

+0

@empo, теперь, когда вы поняли проблему с вашим оригинальным решением, пожалуйста, удалите свой комментарий выше - Это неправда. –

+0

@Tim C: Хороший ответ и +1 (alredy upvoted). –

1

Распространенный способ добиться подобного рода является по соединение требуемых узлов:

<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> 
+0

Это будет работать только в том случае, если гарантируется, что 'title/romali' всегда приходит (в порядке документа) * перед *' title/english'. Правильный способ сделать это - либо использовать конкатенацию, как предложено @Tim C, или, более широко, используя две инструкции 'xsl: sort'. –

+0

@ Dimitre Я вижу, спасибо. Как насчет редактирования сейчас? –

+0

Я все еще думаю, что ** union ** - правильный путь. На самом деле две инструкции по порядку ** не являются правильным. –

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