2011-02-01 4 views
2

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

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?

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

дней не будет повторяться

+0

@StevenWilkins: Может быть повторен дней ? –

+0

@Alejandro - Дни не будут повторяться. – StevenWilkins

+0

Вам нужно рассказать нам, является ли это XSLT 1.0 или 2.0. Проблемы, подобные этой области, всегда проще в 2.0. –

ответ

3

Этот стиль lesheet

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

Edit: Для тех, кто блуждает, сохраняя порядок следования:

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

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

+0

Ницца! Мне нравится, как вы определяете своего рода ассоциативный массив (l, n). Это хорошая вещь о SO. Вы видите лучшие решения, чем ваши собственные. –

+0

+1. Действительно. – Flack

+0

Мне действительно не нравятся решения, зависящие от документа (''). Если вы используете XSLT 2.0, вы можете поместить таблицу lookup в правильную глобальную переменную. С 1.0 в большинстве случаев более эффективно сделать таблицу поиска отдельным XML-документом. Кроме того, если количество данных тривиально мало, таблицы поиска должны использовать ключи. –

1

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

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

+0

Можете ли вы расширить свой ответ, включив пример, который я дал в исходном вопросе, пожалуйста? Или мне просто нужно включить все дни недели? – StevenWilkins

+0

Это нормально (добавлены запятые). –

+0

Это близко, учитывая USM, запятые неуместны MondaySaturday, в воскресенье, мне нужно будет посмотреть, гарантирован ли этот порядок дней. – StevenWilkins

1

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

Предположим, что мы имеем следующий документ 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> 
+0

+1 Обязательное решение XSLT 2.0! –

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