Преобразование кратких дней недели в названия дней в xslt - PullRequest
2 голосов
/ 02 февраля 2011

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

M -> Monday
T -> Tuesday
W -> Wednesday
R -> Thursday
F -> Friday
S -> Saturday
U -> Sunday

Как я могу преобразовать элемент xml, например <days>MRF</days>, в длинную версию <long-days>Monday,Thursday,Friday</long-days>, используя xslt?

Обновление от комментариев

Дни не повторятся

Ответы [ 3 ]

3 голосов
/ 02 февраля 2011

Эта таблица стилей

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:d="day"
 exclude-result-prefixes="d">
    <d:d l="M" n="Monday"/>
    <d:d l="T" n="Tuesday"/>
    <d:d l="W" n="Wednesday"/>
    <d:d l="R" n="Thursday"/>
    <d:d l="F" n="Friday"/>
    <d:d l="S" n="Saturday"/>
    <d:d l="U" n="Sunday"/>
    <xsl:variable name="vDays" select="document('')/*/d:d"/>
    <xsl:template match="days">
        <long-days>
            <xsl:apply-templates
                 select="$vDays[contains(current(),@l)]"/>
        </long-days>
    </xsl:template>
    <xsl:template match="d:d">
        <xsl:value-of select="@n"/>
        <xsl:if test="position()!=last()">,</xsl:if>
    </xsl:template>
</xsl:stylesheet>

С этим входом:

<days>MRF</days>

Выход:

<long-days>Monday,Thursday,Friday</long-days>

Редактировать : Для тех, кто бродит, сохраняя порядок последовательности:

<xsl:variable name="vCurrent" select="current()"/>
<xsl:apply-templates
         select="$vDays[contains($vCurrent,@l)]">
    <xsl:sort select="substring-before($vCurrent,@l)"/>
</xsl:apply-templates>

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

1 голос
/ 02 февраля 2011

В текущем принятом решении всегда отображаются длинные имена дней в хронологическом порядке и, кроме того, не отображаются повторяющиеся (с тем же кодом) дни.

Предположим, у нас есть следующий XML-документ :

<days>STMSU</days>

I. Это XSLT 1.0 преобразование :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my" >
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <my:days>
  <M>Monday</M>
  <T>Tuesday</T>
  <W>Wednesday</W>
  <R>Thursday</R>
  <F>Friday</F>
  <S>Saturday</S>
  <U>Sunday</U>
 </my:days>

 <xsl:key name="kLongByShort" match="my:days/*"
  use="name()"/>

  <xsl:variable name="vstylesheet"
   select="document('')"/>

 <xsl:template match="days">
  <long-days>
   <xsl:call-template name="expand"/>
  </long-days>
 </xsl:template>

 <xsl:template name="expand">
  <xsl:param name="pcodeString" select="."/>

  <xsl:if test="$pcodeString">
    <xsl:variable name="vchar" select=
    "substring($pcodeString,1,1)"/>
    <xsl:for-each select="$vstylesheet">
     <xsl:value-of select=
     "concat(key('kLongByShort',$vchar),
             substring(',',1,string-length($pcodeString)-1)
            )
     "/>
    </xsl:for-each>

    <xsl:call-template name="expand">
     <xsl:with-param name="pcodeString" select=
      "substring($pcodeString,2)"/>
    </xsl:call-template>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

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

<long-days>Saturday,Tuesday,Monday,Saturday,Sunday</long-days>

II. Это XSLT 2.0 преобразование :

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema"
 exclude-result-prefixes="xs">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:variable name="vshortCodes" as="xs:integer+"
 select="string-to-codepoints('MTWRFSU')"/>

 <xsl:variable name="vlongDays" as="xs:string+"
 select="'Monday','Tuesday','Wenesday','Thursday',
         'Friday','Saturday','Sunday'
 "/>

 <xsl:template match="days">
  <long-days>
    <xsl:for-each select="string-to-codepoints(.)">
      <xsl:value-of separator="" select=
      "for $pos in position() ne last()
        return
         ($vlongDays[index-of($vshortCodes,current())],
          ','[$pos])
      "/>
    </xsl:for-each>
  </long-days>
 </xsl:template>
</xsl:stylesheet>

при применении к тому же XML-документу :

<days>STMSU</days>

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

<long-days>Saturday,Tuesday,Monday,Saturday,Sunday</long-days>
1 голос
/ 02 февраля 2011

Это должно сделать это ... (Хотя могут быть более элегантные решения ...; -)

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

<xsl:template match="/days">
    <long-days>
        <xsl:if test="contains(.,'M')">Monday<xsl:if test="string-length(substring-before(.,'M'))=string-length(.)-1">,</xsl:if></xsl:if>
        <xsl:if test="contains(.,'T')">Tuesday<xsl:if test="string-length(substring-before(.,'T'))=string-length(.)-1">,</xsl:if></xsl:if>
        <xsl:if test="contains(.,'W')">Wednesday<xsl:if test="string-length(substring-before(.,'W'))=string-length(.)-1">,</xsl:if></xsl:if>
        <xsl:if test="contains(.,'R')">Thursday<xsl:if test="string-length(substring-before(.,'R'))=string-length(.)-1">,</xsl:if></xsl:if>
        <xsl:if test="contains(.,'F')">Friday<xsl:if test="string-length(substring-before(.,'F'))=string-length(.)-1">,</xsl:if></xsl:if>
        <xsl:if test="contains(.,'S')">Saturday<xsl:if test="string-length(substring-before(.,'S'))=string-length(.)-1">,</xsl:if></xsl:if>
        <xsl:if test="contains(.,'U')">Sunday<xsl:if test="string-length(substring-before(.,'U'))=string-length(.)-1">,</xsl:if></xsl:if>
    </long-days>
</xsl:template>

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...