?
Solved

Format Date in XSL?

Posted on 2006-05-14
14
Medium Priority
?
623 Views
Last Modified: 2007-12-19
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,







0
Comment
Question by:marcjjrd
  • 8
  • 6
14 Comments
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 16680225
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
 

Author Comment

by:marcjjrd
ID: 16680314
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
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 16680319
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
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 

Author Comment

by:marcjjrd
ID: 16680366
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
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 16680412
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
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 16680419
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
 

Author Comment

by:marcjjrd
ID: 16680448
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
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 16680572
I see,
I am in Belgium Europe
it is 10:30 AM here,
see you this afternoon
cheers
0
 
LVL 60

Accepted Solution

by:
Geert Bormans earned 1000 total points
ID: 16681697
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
 

Author Comment

by:marcjjrd
ID: 16729394
The easy solution is here:

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

But thanks for all your help.

N
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 16729788
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
 

Author Comment

by:marcjjrd
ID: 16729798
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
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 16729842
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
 

Author Comment

by:marcjjrd
ID: 16729845
It works like a dream. Thanks for all your help.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The Problem How to write an Xquery that works like a SQL outer join, providing placeholders for absent data on the outer side?  I give a bit more background at the end. The situation expressed as relational data Let’s work through this.  I’ve …
The Client Need Led Us to RSS I recently had an investment company ask me how they might notify their constituents about their newsworthy publications.  Probably you would think "Facebook" or "Twitter" but this is an interesting client.  Their cons…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
As many of you are aware about Scanpst.exe utility which is owned by Microsoft itself to repair inaccessible or damaged PST files, but the question is do you really think Scanpst.exe is capable to repair all sorts of PST related corruption issues?
Suggested Courses
Course of the Month13 days, 14 hours left to enroll

809 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question