Format Date in XSL?

I'm using XSL to output XML that makes a table of class names, reading and dates.

The XSL:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="Rows">
<xsl:call-template name="Tabla"/>
</xsl:template>
<!-- Tabla -->
<xsl:template name="Tabla">
<table width="100%" cellpading="1">
<tbody>    
<tr>        
<th>Title</th>        
<th>Reading</th>        
<th>Date</th>      
</tr>      
<xsl:for-each select="Row">      
<tr>        
<td><xsl:value-of select="Title"/></td>        
<td><xsl:value-of select="Reading"/></td>
<td><xsl:value-of select="Date"/></td>      
</tr>      
</xsl:for-each>
</tbody></table></xsl:template></xsl:stylesheet>

And the resulting XML:

<Rows>
  <Row>
    <Title>Artistic Body</Title>
    <Reading />
    <Date>8/28/2006 12:00:00 AM</Date>
  </Row>
  <Row>
    <Title>Artistic Body</Title>
    <Reading />
    <Date>9/4/2006 12:00:00 AM</Date>
  </Row>
  <Row>
    <Title>Artistic Body</Title>
    <Reading />
    <Date>9/11/2006 12:00:00 AM</Date>
  </Row>
</Rows>

I'd like the dates to come out looking like this: Monday, 28 August rather than 8/28/2006 12:00:00 AM

Any help to make my XSL do that?

Thanks,







marcjjrdAsked:
Who is Participating?
 
Geert BormansInformation ArchitectCommented:
marcjjrd,

here is a stylesheet that works with msxml
(and I assume MS stuffed msxml in Sharepoint)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0"
    xmlns:map="urn:internal"
    xmlns:date="http://exslt.org/dates-and-times"
     extension-element-prefixes="date"
     exclude-result-prefixes="map date">
     
     <xsl:import href="datetime.xsl" />

    <xsl:template match="/">
        <xsl:call-template name="formatDate">
            <xsl:with-param name="date" select="//Date"/>
        </xsl:call-template>
    </xsl:template>
   
    <xsl:template name="formatDate">
        <xsl:param name="date"/>
        <!-- normalised month to be sure it is two digits -->
        <xsl:variable name="normMonth">
            <xsl:choose>
                <xsl:when test="string-length(substring-before($date, '/')) &gt; 1">
                    <xsl:value-of select="substring-before($date, '/')"/>
                </xsl:when>
                <xsl:otherwise><xsl:text>0</xsl:text><xsl:value-of select="substring-before($date, '/')"/></xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <!-- normalised day to be sure it is two digits -->
        <xsl:variable name="normDay">
            <xsl:choose>
                <xsl:when test="string-length(substring-before(substring-after($date, '/'), '/')) &gt; 1">
                    <xsl:value-of select="substring-before(substring-after($date, '/'), '/')"/>
                </xsl:when>
                <xsl:otherwise><xsl:text>0</xsl:text><xsl:value-of select="substring-before(substring-after($date, '/'), '/')"/></xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <!-- normalised date to be sure it can be used in the day-in-week template -->
        <xsl:variable name="normDate">
            <xsl:value-of select="substring-before(substring-after(substring-after($date, '/'), '/'), ' ')"/>
            <xsl:text>-</xsl:text>
            <xsl:value-of select="$normMonth"/>
            <xsl:text>-</xsl:text>
            <xsl:value-of select="$normDay"/>
        </xsl:variable>
        <!-- get the numeric version of the weekday -->
        <xsl:variable name="weekDayNum">
    <xsl:call-template name="date:day-in-week">
        <xsl:with-param name="date-time" select="$normDate" />
    </xsl:call-template>
       </xsl:variable>
        <!-- build the output format date  -->
        <xsl:value-of select="document('')//map:dayNum[text() = $weekDayNum]/@id"/>
        <xsl:text>, </xsl:text>
        <xsl:value-of select="substring-before(substring-after($date, '/'), '/')"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="document('')//map:monthNum[text() = $normMonth]/@id"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="substring-before(substring-after(substring-after($date, '/'), '/'), ' ')"/>
   
    </xsl:template>
    <!--  lookup tables  -->
    <map:dates>
        <map:monthNum id="January">01</map:monthNum>
        <map:monthNum id="February">02</map:monthNum>
        <map:monthNum id="March">03</map:monthNum>
        <map:monthNum id="April">04</map:monthNum>
        <map:monthNum id="May">05</map:monthNum>
        <map:monthNum id="June">06</map:monthNum>
        <map:monthNum id="July">07</map:monthNum>
        <map:monthNum id="Augustus">08</map:monthNum>
        <map:monthNum id="September">09</map:monthNum>
        <map:monthNum id="October">10</map:monthNum>
        <map:monthNum id="November">11</map:monthNum>
        <map:monthNum id="December">12</map:monthNum>
 
        <map:dayNum id="Sunday">1</map:dayNum>
        <map:dayNum id="Monday">2</map:dayNum>
        <map:dayNum id="Tuesday">3</map:dayNum>
        <map:dayNum id="Wednesday">4</map:dayNum>
        <map:dayNum id="Thursday">5</map:dayNum>
        <map:dayNum id="Friday">6</map:dayNum>
        <map:dayNum id="Saturday">7</map:dayNum>
       
    </map:dates>
   
</xsl:stylesheet>

you will need Jeni Tenisson's named template for this
http://www.exslt.org/date/functions/day-in-week/index.html

I will paste it in here
make sure you safe it with the name "datetime.xsl"

<?xml version="1.0" ?>
   <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="http://exslt.org/dates-and-times" extension-element-prefixes="date">
      <xsl:param name="date:date-time" select="'2000-01-01T00:00:00Z'" />
      <date:month-lengths>
          <date:month>31</date:month>
          <date:month>28</date:month>
          <date:month>31</date:month>
          <date:month>30</date:month>
          <date:month>31</date:month>
          <date:month>30</date:month>
          <date:month>31</date:month>
          <date:month>31</date:month>
          <date:month>30</date:month>
          <date:month>31</date:month>
          <date:month>30</date:month>
          <date:month>31</date:month>
      </date:month-lengths>
       <xsl:template name="date:day-in-week">
           <xsl:param name="date-time">
               <xsl:choose>
                   <xsl:when test="function-available('date:date-time')">
                      <xsl:value-of select="date:date-time()" />
                  </xsl:when>
                   <xsl:otherwise>
                      <xsl:value-of select="$date:date-time" />
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:param>
          <xsl:variable name="neg" select="starts-with($date-time, '-')" />
           <xsl:variable name="dt-no-neg">
              <xsl:choose>
                  <xsl:when test="$neg or starts-with($date-time, '+')">
                      <xsl:value-of select="substring($date-time, 2)" />
                  </xsl:when>
                   <xsl:otherwise>
                      <xsl:value-of select="$date-time" />
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:variable>
          <xsl:variable name="dt-no-neg-length" select="string-length($dt-no-neg)" />
           <xsl:variable name="timezone">
               <xsl:choose>
                  <xsl:when test="substring($dt-no-neg, $dt-no-neg-length) = 'Z'">Z</xsl:when>
                   <xsl:otherwise>
                      <xsl:variable name="tz" select="substring($dt-no-neg, $dt-no-neg-length - 5)" />
                      <xsl:if test="(substring($tz, 1, 1) = '-' or substring($tz, 1, 1) = '+') and substring($tz, 4, 1) = ':'">
                          <xsl:value-of select="$tz" />
                      </xsl:if>
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:variable>
          <xsl:variable name="day-of-week">
              <xsl:if test="not(string($timezone)) or $timezone = 'Z' or (substring($timezone, 2, 2) &lt;= 23 and substring($timezone, 5, 2) &lt;= 59)">
                  <xsl:variable name="dt" select="substring($dt-no-neg, 1, $dt-no-neg-length - string-length($timezone))" />
                  <xsl:variable name="dt-length" select="string-length($dt)" />
                  <xsl:variable name="year" select="substring($dt, 1, 4)" />
                  <xsl:variable name="leap" select="(not($year mod 4) and $year mod 100) or not($year mod 400)" />
                  <xsl:variable name="month" select="substring($dt, 6, 2)" />
                  <xsl:variable name="day" select="substring($dt, 9, 2)" />
                  <xsl:if test="number($year) and substring($dt, 5, 1) = '-' and $month &lt;= 12 and substring($dt, 8, 1) = '-' and $day &lt;= 31 and ($dt-length = 10 or (substring($dt, 11, 1) = 'T' and substring($dt, 12, 2) &lt;= 23 and substring($dt, 14, 1) = ':' and substring($dt, 15, 2) &lt;= 59 and substring($dt, 17, 1) = ':' and substring($dt, 18) &lt;= 60))">
                      <xsl:variable name="month-days" select="sum(document('')/*/date:month-lengths/date:month[position() &lt; $month])" />
                           <xsl:variable name="days">
                               <xsl:choose>
                                   <xsl:when test="$leap and $month > 2">
                                      <xsl:value-of select="$month-days + $day + 1" />
                                  </xsl:when>
                                   <xsl:otherwise>
                                      <xsl:value-of select="$month-days + $day" />
                                  </xsl:otherwise>
                              </xsl:choose>
                          </xsl:variable>
                          <xsl:variable name="y-1" select="$year - 1" />
                          <xsl:value-of select="(($y-1 + floor($y-1 div 4) - floor($y-1 div 100) + floor($y-1 div 400) + $days) mod 7) + 1" />
                  </xsl:if>
              </xsl:if>
          </xsl:variable>
          <xsl:value-of select="number($day-of-week)" />
      </xsl:template>
  </xsl:stylesheet>

good luck

Geert
0
 
Geert BormansInformation ArchitectCommented:
Hi marcjjrd,

you will find a solution in my answer to this question
http://www.experts-exchange.com/Web/Web_Languages/XML/Q_21546666.html


Cheers!
0
 
marcjjrdAuthor Commented:
Thanks a lot, Gertone.

I get an error:

The variable or param 'weekday' is either not defined or it is out of scope.

Perhaps because there's no day of the week in the incoming data?


0
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

 
Geert BormansInformation ArchitectCommented:
marcjjrd,

I don't think the above referenced question gives you the entire solution.
Here is a named template that fits your need better
(embedded in a test stylesheet)

note the references to the map namespace for the lookup table

it doesn't give you the day though,
we need some extension for that
which XSLT processor are you using?

cheers

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0"
    xmlns:map="urn:internal"
     exclude-result-prefixes="map">
    <xsl:template match="/">
        <xsl:call-template name="formatDate">
            <xsl:with-param name="date" select="//Date"/>
        </xsl:call-template>
    </xsl:template>
   
    <xsl:template name="formatDate">
        <xsl:param name="date"/>
        <xsl:variable name="normMonth">
            <xsl:choose>
                <xsl:when test="string-length(substring-before($date, '/')) &gt; 1">
                    <xsl:value-of select="substring-before($date, '/')"/>
                </xsl:when>
                <xsl:otherwise><xsl:text>0</xsl:text><xsl:value-of select="substring-before($date, '/')"/></xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:value-of select="substring-before(substring-after($date, '/'), '/')"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="document('')//map:monthNum[text() = $normMonth]/@id"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="substring-before(substring-after(substring-after($date, '/'), '/'), ' ')"/>
   
    </xsl:template>
    <map:dates>
        <map:monthNum id="January">01</map:monthNum>
        <map:monthNum id="February">02</map:monthNum>
        <map:monthNum id="March">03</map:monthNum>
        <map:monthNum id="April">04</map:monthNum>
        <map:monthNum id="May">05</map:monthNum>
        <map:monthNum id="June">06</map:monthNum>
        <map:monthNum id="July">07</map:monthNum>
        <map:monthNum id="Augustus">08</map:monthNum>
        <map:monthNum id="September">09</map:monthNum>
        <map:monthNum id="October">10</map:monthNum>
        <map:monthNum id="November">11</map:monthNum>
        <map:monthNum id="December">12</map:monthNum>
                                                       
    </map:dates>
   
</xsl:stylesheet>
0
 
marcjjrdAuthor Commented:
To tell you the truth, I have no idea what that means.

I'm using the XSL is the csegRollUp web part for SharePoint. I assume I'm using SharePoint's native XSL processor.

Thanks for all your help.
0
 
Geert BormansInformation ArchitectCommented:
marcjjrd,

If you were using Xalan-J, or another processor that supports the exslt date:day-in week extension,
this template will give you what you need

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0"
    xmlns:map="urn:internal"
    xmlns:date="http://exslt.org/dates-and-times"
     extension-element-prefixes="date"
     exclude-result-prefixes="map date">
    <xsl:template match="/">
        <xsl:call-template name="formatDate">
            <xsl:with-param name="date" select="//Date"/>
        </xsl:call-template>
    </xsl:template>
   
    <xsl:template name="formatDate">
        <xsl:param name="date"/>
        <xsl:variable name="normMonth">
            <xsl:choose>
                <xsl:when test="string-length(substring-before($date, '/')) &gt; 1">
                    <xsl:value-of select="substring-before($date, '/')"/>
                </xsl:when>
                <xsl:otherwise><xsl:text>0</xsl:text><xsl:value-of select="substring-before($date, '/')"/></xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="normDay">
            <xsl:choose>
                <xsl:when test="string-length(substring-before(substring-after($date, '/'), '/')) &gt; 1">
                    <xsl:value-of select="substring-before(substring-after($date, '/'), '/')"/>
                </xsl:when>
                <xsl:otherwise><xsl:text>0</xsl:text><xsl:value-of select="substring-before(substring-after($date, '/'), '/')"/></xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <xsl:variable name="normDate">
            <xsl:value-of select="substring-before(substring-after(substring-after($date, '/'), '/'), ' ')"/>
            <xsl:text>-</xsl:text>
            <xsl:value-of select="$normMonth"/>
            <xsl:text>-</xsl:text>
            <xsl:value-of select="$normDay"/>
        </xsl:variable>
        <xsl:value-of select="document('')//map:dayNum[text() = date:day-in-week($normDate)]/@id"/>
        <xsl:text>, </xsl:text>
        <xsl:value-of select="substring-before(substring-after($date, '/'), '/')"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="document('')//map:monthNum[text() = $normMonth]/@id"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="substring-before(substring-after(substring-after($date, '/'), '/'), ' ')"/>
   
    </xsl:template>
    <map:dates>
        <map:monthNum id="January">01</map:monthNum>
        <map:monthNum id="February">02</map:monthNum>
        <map:monthNum id="March">03</map:monthNum>
        <map:monthNum id="April">04</map:monthNum>
        <map:monthNum id="May">05</map:monthNum>
        <map:monthNum id="June">06</map:monthNum>
        <map:monthNum id="July">07</map:monthNum>
        <map:monthNum id="Augustus">08</map:monthNum>
        <map:monthNum id="September">09</map:monthNum>
        <map:monthNum id="October">10</map:monthNum>
        <map:monthNum id="November">11</map:monthNum>
        <map:monthNum id="December">12</map:monthNum>
 
        <map:dayNum id="Sunday">1</map:dayNum>
        <map:dayNum id="Monday">2</map:dayNum>
        <map:dayNum id="Tuesday">3</map:dayNum>
        <map:dayNum id="Wednesday">4</map:dayNum>
        <map:dayNum id="Thursday">5</map:dayNum>
        <map:dayNum id="Friday">6</map:dayNum>
        <map:dayNum id="Saturday">7</map:dayNum>
       
    </map:dates>
   
</xsl:stylesheet>
0
 
Geert BormansInformation ArchitectCommented:
marcjjrd,
> I assume I'm using SharePoint's native XSL processor.

I will post an alternative that should work with Sharepoint, later today
did you get the first template working?

cheers

Geert
0
 
marcjjrdAuthor Commented:
I'll get to it when it's not three in the morning (I don't know where you are, but in Chicago, it's well past bed time).

Thanks for all your help, and we'll regroup after sleep!
0
 
Geert BormansInformation ArchitectCommented:
I see,
I am in Belgium Europe
it is 10:30 AM here,
see you this afternoon
cheers
0
 
marcjjrdAuthor Commented:
The easy solution is here:

http://foros.ideseg.com/viewtopic.php?t=91&sid=aa24b06afe6f16e4ee98596514194259

But thanks for all your help.

N
0
 
Geert BormansInformation ArchitectCommented:
you are welcome

if you post a link in this forum,
make sure you don't need a password to view it...

I am very much interested in the easy solution
0
 
marcjjrdAuthor Commented:
Sorry, here's the solution from "JamesGrote" at the forums at www.ideseg.com:

I have a solution, though it may not be the best way to do this. I added a simple C# script to the XSL to format my date field.

Here's the top of my XSL (must reference msxsl):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:utils="urn:script-items">
<msxsl:script language="C#" implements-prefix="utils">
<![CDATA[
public string DateToString(string sDate)
{
if (sDate.Length > 0)
{
DateTime dDate = DateTime.Parse(sDate);
return dDate.ToShortDateString();
}
else
{
return "sDate";
}
}
]]>
</msxsl:script>


And here's how my date field is displayed:
<xsl:value-of select="utils:DateToString(Modified)" />


I'm new to XSL so don't know if there's a way to do this directly in xsl, but at least this works. The ability to drop C# right into xsl is actually quite powerful, as you could easily write more complex functions to do really cool stuff.

Anyway, hope this helps!
James
0
 
Geert BormansInformation ArchitectCommented:
thanks for the post

this shows that indeed XSLT is not the preferred language of choice for this type of processing (it is never meant to be that)

the problem of this solution is that it is msxml only, so it ain't very portable... but if it works for you it is good

cheers
0
 
marcjjrdAuthor Commented:
It works like a dream. Thanks for all your help.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.