将一周的短格式天数转换为xslt中的天名称

时间:2011-02-01 22:05:50

标签: xslt

我有一些简短的日期名称,如:

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

如何使用xslt将<days>MRF</days>等xml元素转换为长版本<long-days>Monday,Thursday,Friday</long-days>

从评论中更新

  

天不会重复

3 个答案:

答案 0 :(得分:3)

此样式表

<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 :(得分: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>

答案 2 :(得分:1)

当前接受的解决方案始终按时间顺序显示长日名称,此外,它不会显示重复(使用相同代码)的日期。

假设我们有以下XML文档

<days>STMSU</days>

<强>予。这个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>