XSL prob.

T

Thomas

Hi

I have an XSL stylesheet:

<xsl:for-each select="TRACKS/TRACK">
<tr class="TDL">
<td width="90%"><xsl:number value="position()" format="1" /> -
<xsl:value-of select="TRACKTITLE"/></td>
<td width="10%" align="center"><a href="{TRACKURL}"
target="_blank">More info!</a></td>
</tr>
</xsl:for-each>


I wan't to make every second <tr class> aligned to TDU, which I have in the
CSS. How is this possible?

Regards,
Kenneth
 
M

Marrow

Hi Kenneth,

Try one of the following (all do the same - in a slightly different way)...

<xsl:for-each select="TRACKS/TRACK">
<tr class="TDL">
<xsl:if test="position() mod 2 = 0">
<xsl:attribute name="class">TDU</xsl:attribute>
</xsl:if>
<td width="90%">
<xsl:number value="position()" format="1" /> -
<xsl:value-of select="TRACKTITLE"/>
</td>
<td width="10%" align="center">
<a href="{TRACKURL}" target="_blank">More info!</a>
</td>
</tr>
</xsl:for-each>

<xsl:for-each select="TRACKS/TRACK">
<tr>
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="position() mod 2 = 1">
<xsl:text>TDL</xsl:text>
</xsl:when>
<xsl:eek:therwise>
<xsl:text>TDU</xsl:text>
</xsl:eek:therwise>
</xsl:choose>
</xsl:attribute>
<td width="90%">
<xsl:number value="position()" format="1" /> -
<xsl:value-of select="TRACKTITLE"/>
</td>
<td width="10%" align="center">
<a href="{TRACKURL}" target="_blank">More info!</a>
</td>
</tr>
</xsl:for-each>

<xsl:for-each select="TRACKS/TRACK">
<tr class="{substring('TDUTDL',((position() mod 2) * 3) + 1,3)}">
<td width="90%">
<xsl:number value="position()" format="1" /> -
<xsl:value-of select="TRACKTITLE"/>
</td>
<td width="10%" align="center">
<a href="{TRACKURL}" target="_blank">More info!</a>
</td>
</tr>
</xsl:for-each>

Hope this helps
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator
 
T

Thomas

Hi Marrow.

Damn! You nailed it, thanks.



Marrow said:
Hi Kenneth,

Try one of the following (all do the same - in a slightly different way)...

<xsl:for-each select="TRACKS/TRACK">
<tr class="TDL">
<xsl:if test="position() mod 2 = 0">
<xsl:attribute name="class">TDU</xsl:attribute>
</xsl:if>
<td width="90%">
<xsl:number value="position()" format="1" /> -
<xsl:value-of select="TRACKTITLE"/>
</td>
<td width="10%" align="center">
<a href="{TRACKURL}" target="_blank">More info!</a>
</td>
</tr>
</xsl:for-each>

<xsl:for-each select="TRACKS/TRACK">
<tr>
<xsl:attribute name="class">
<xsl:choose>
<xsl:when test="position() mod 2 = 1">
<xsl:text>TDL</xsl:text>
</xsl:when>
<xsl:eek:therwise>
<xsl:text>TDU</xsl:text>
</xsl:eek:therwise>
</xsl:choose>
</xsl:attribute>
<td width="90%">
<xsl:number value="position()" format="1" /> -
<xsl:value-of select="TRACKTITLE"/>
</td>
<td width="10%" align="center">
<a href="{TRACKURL}" target="_blank">More info!</a>
</td>
</tr>
</xsl:for-each>

<xsl:for-each select="TRACKS/TRACK">
<tr class="{substring('TDUTDL',((position() mod 2) * 3) + 1,3)}">
<td width="90%">
<xsl:number value="position()" format="1" /> -
<xsl:value-of select="TRACKTITLE"/>
</td>
<td width="10%" align="center">
<a href="{TRACKURL}" target="_blank">More info!</a>
</td>
</tr>
</xsl:for-each>

Hope this helps
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator
 
T

Thomas

Hi

I have another prob. Is it possible to convert a unix timestamp to a
readable date with XSL?

Kenneth
 
T

Thomas

Can you give an example of a "Unix timestamp" and a "readable date"?

Unix timestamp: 875996580
Readable converted date/time: 1997-10-04 22:23:00'

Kenneth
 
D

Dimitre Novatchev

Can you give an example of a "Unix timestamp" and a "readable date"?
Unix timestamp: 875996580
Readable converted date/time: 1997-10-04 22:23:00'

And what's its meaning (e.g. number of seconds after some date)?


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 
J

Jens M. Felderhoff

Thomas said:
I have another prob. Is it possible to convert a unix timestamp to a
readable date with XSL?

Yes, because XSLT is Turing complete. However, you'll have to roll
your own conversion because there's neither an XSLT nor XPath function
that'll do the job for you.

Cheers

Jens
 
M

Martin Boehm

Thomas said:
Source: http://www.mysql.com/doc/en/Date_and_time_functions.html

It would be a lot easier if they pull the data out of the database as
a readable date instead of unix timestamp, but they don't. :(

Since a UNIX timestamp is the number of seconds since midnight, 1st
January 1970, it would be an "easy" addition of seconds to a date. But
XSL is not capable of that, AFAICS.

What you could do - write a web page accepting a timestamp as GET
parameter and let it return a small XML file to your XSL processor.

Given a return XML like:
<?xml version="1.0"?>
<formatted>1997-10-04 22:23:00</formatted>

then I would think of:
<xsl:value-of
select="document(concat('http://localhost/convert.php&amp;timestamp=',
$timestamp))/formatted" />

This would return the contents of the XML document's "formatted"
element, or what ever you'd like to call it.
PHP does contain date and time functions capable of converting
timestamps, so the implementation on the PHP side should be quite
straightforward.

You could even improve performance by handing all timestamps in your
document over to PHP simultaneously, as a seperated list of values
(build that by recursive call-template's). So you will need to use
document() only once per processed XML file.

just an idea,

Martin
 
M

Martin Boehm

Jens M. Felderhoff said:
Thomas said:
I have another prob. Is it possible to convert a unix timestamp to a
readable date with XSL?

Yes, because XSLT is Turing complete. However, you'll have to roll
your own conversion [...]

Which would cause quite a headache and bury efficiency really big time.
XSLT is not the adequate instrument for such a task, except for academic
purposes maybe. But regarding the wording of the question you are
absolutely right. ;-)

Martin
 
D

Dimitre Novatchev

Martin Boehm said:
Jens M. Felderhoff said:
Thomas said:
I have another prob. Is it possible to convert a unix timestamp to a
readable date with XSL?

Yes, because XSLT is Turing complete. However, you'll have to roll
your own conversion [...]

Which would cause quite a headache and bury efficiency really big time.
XSLT is not the adequate instrument for such a task, except for academic
purposes maybe. But regarding the wording of the question you are
absolutely right. ;-)

This is not true!

Using the datetime_lib.xsl stylesheet, which comes with the XSelerator (one
can obtain it free with the trial download), the code to convert a Unix
timestamp to a formatted date is just a few lines (11 lines for the called
template):

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

<xsl:import href="E:\Program
Files\Marrowsoft\Xselerator25\Samples\Libraries\datetime_lib.xsl"/>

<xsl:eek:utput method="text"/>

<xsl:variable name="vDaySecs" select="86400"/>

<xsl:template match="/">
<xsl:call-template name="unix-timestamp-to-datetime">
<xsl:with-param name="pTimeStamp" select="875996580"/>
</xsl:call-template>
</xsl:template>

<xsl:template name="unix-timestamp-to-datetime">
<xsl:param name="pTimeStamp" select="0"/>

<xsl:variable name="vBase">
<xsl:call-template name="date-to-julian-day">
<xsl:with-param name="date" select="'1970-01-01'"/>
</xsl:call-template>
</xsl:variable>

<xsl:call-template name="float-to-date-time">
<xsl:with-param name="value" select="$vBase + $pTimeStamp div
$vDaySecs"/>
</xsl:call-template>
</xsl:template>

</xsl:stylesheet>

When this transformation is applied on any source.xml (not used), the wanted
result is produced:

1997-10-04T20:23:00


To see the real power of this pure XSLT 1.0 library, do have a look at the
Calendar Application I wrote two years ago:

http://www.topxml.com/code/default.asp?p=3&id=v20020711152545

FYI, it is really efficient -- on my PC the transformation time is just 93
milliseconds.


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 
M

Martin Boehm

I have another prob. Is it possible to convert a unix timestamp to
a readable date with XSL?

Yes, because XSLT is Turing complete. However, you'll have to roll
your own conversion [...]

Which would cause quite a headache and bury efficiency really big
time. XSLT is not the adequate instrument for such a task, except
for academic purposes maybe. But regarding the wording of the
question you are absolutely right. ;-)

This is not true!

[example snipped]

I admit, I was not aware of that.
[...]

FYI, it is really efficient -- on my PC the transformation time is
just 93 milliseconds.

Whatever "my PC" means. SCNR ;-) Besides that you forgot to compare it
to the time maybe PHP would need to do it. The word "efficient" is quite
meaningless if you give only one number.

BTW I am not sure if one can call doing about 10 conversions per second
"efficient" in context of the simplicity of this task, given the
hardware that you use.

What I thought of was putting the algorithms together myself, and my
subjective impression was that the outcome would not be optimal under
the best of circumstances, and that it would not approximate solutions
more adequate for the problem.

Martin
 
D

Dimitre Novatchev

FYI, it is really efficient -- on my PC the transformation time is
Whatever "my PC" means. SCNR ;-)

My PC is 2 years old 1.7GHz Pentium with 256MB RAM running W2K
Besides that you forgot to compare it
to the time maybe PHP would need to do it. The word "efficient" is quite
meaningless if you give only one number.

By efficient I mean that it is not obviously a bottleneck. In this case one
would use an existing solution, which BTW is 100% portable.
BTW I am not sure if one can call doing about 10 conversions per second
"efficient" in context of the simplicity of this task, given the
hardware that you use.

You misunderstood me -- the reported time was for the complete Calendar
Application, which does many hundreds of times more...

The time for a single conversion using MSXML4 on my PC is 0.3 milliseconds.


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 
D

Dimitre Novatchev

The time for a single conversion using MSXML4 on my PC is 0.3
milliseconds.

Some more accurate timing:

The time for 104 conversions is ~ 7.5 milliseconds.

This makes 0.073 milliseconds for a single conversion or ~ 13700 conversions
per second.


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 
M

Martin Boehm

The time for 104 conversions is ~ 7.5 milliseconds.

This makes 0.073 milliseconds for a single conversion or ~ 13700
conversions per second.

Just estimated the PHP solution:
(I hold the difference between the power of your CPU and that of mine
for quite negligible, and the amount RAM does not matter here. I used a
for loop containing a call to the PGP date() function.)

My 1.8 GHz P4 with 512 MB of RAM (Win2k, too) did 1.000.000 conversions
in a 10 reiterations average of 7.57 seconds, this breaks down to about
132100 per second. For a single conversion that would be (quite exactly)
7,56998 * 10^-6 seconds, or ~0.076 milliseconds.

I am amazed. :)

surrendering,

Martin

P.S.: Would you mind do post or mail the code you used so I can make a
direct comparison on that? Thanks!
 
M

Marrow

Hi Kenneth,

Using some functions from our datetime_lib.xsl (www.marrowsoft.com -
libraries included in the trial installer) you could do...

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="unix_timestamp" select="875996580"/>
<xsl:variable name="jd19700101" select="2440588"/>
<xsl:call-template name="float-to-date-time">
<xsl:with-param name="value" select="$jd19700101 + ($unix_timestamp div
(24 * 60 * 60))"/>
</xsl:call-template>
</xsl:template>

<!--
==========================================================================
Template: float-to-date-time
Description: Convert a floating point value representing a date/time to
a date/time string.
Parameters:-
<value> the value to be converted
<round-seconds> if true then the seconds are not quoted on the output
and, if the seconds are 59 then hour/minute is rounded
(this is useful because some processors have limited
floating point precision to cope with the seconds)
========================================================================== -
->
<xsl:template name="float-to-date-time">
<xsl:param name="value" select="number(0)"/>
<xsl:param name="round-seconds" select="false()"/>
<xsl:variable name="date">
<xsl:call-template name="julian-day-to-date">
<xsl:with-param name="julian-day" select="floor($value)"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="t1" select="$value - floor($value)"/>
<xsl:variable name="h" select="floor($t1 div (1 div 24))"/>
<xsl:variable name="t2" select="$t1 - ($h * (1 div 24))"/>
<xsl:variable name="m" select="floor($t2 div (1 div 1440))"/>
<xsl:variable name="t3" select="$t2 - ($m * (1 div 1440))"/>
<xsl:choose>
<xsl:when test="$round-seconds">
<xsl:variable name="s" select="$t3 div (1 div 86400)"/>
<xsl:variable name="h2">
<xsl:choose>
<xsl:when test="($s &gt;= 59) and ($m = 59)"><xsl:value-of select="$h +
1"/></xsl:when>
<xsl:eek:therwise><xsl:value-of select="$h"/></xsl:eek:therwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="m2">
<xsl:choose>
<xsl:when test="($s &gt;= 59) and ($m = 59)">0</xsl:when>
<xsl:when test="($s &gt;= 59)"><xsl:value-of select="$m +
1"/></xsl:when>
<xsl:eek:therwise><xsl:value-of select="$m"/></xsl:eek:therwise>
</xsl:choose>
</xsl:variable>
<!-- pad final time result -->
<xsl:variable name="hh" select="concat(substring('00',1,2 -
string-length(string($h2))),string($h2))"/>
<xsl:variable name="mm" select="concat(substring('00',1,2 -
string-length(string($m2))),string($m2))"/>
<!-- final output resultant -->
<xsl:value-of select="concat($date,'T',$hh,':',$mm)"/>
</xsl:when>
<xsl:eek:therwise>
<xsl:variable name="s" select="floor($t3 div (1 div 86400))"/>
<!-- pad final time result -->
<xsl:variable name="hh" select="concat(substring('00',1,2 -
string-length(string($h))),string($h))"/>
<xsl:variable name="mm" select="concat(substring('00',1,2 -
string-length(string($m))),string($m))"/>
<xsl:variable name="ss" select="concat(substring('00',1,2 -
string-length(string($s))),string($s))"/>
<!-- final output resultant -->
<xsl:value-of select="concat($date,'T',$hh,':',$mm,':',$ss)"/>
</xsl:eek:therwise>
</xsl:choose>
</xsl:template>

<!--
==========================================================================
Template: julian-day-to-date
Description: Convert a julian day to date
Parameters:-
<julian-day>
========================================================================== -
->
<xsl:template name="julian-day-to-date">
<xsl:param name="julian-day" select="number(0)"/>
<!-- pre-calcs -->
<xsl:variable name="la" select="$julian-day + 68569"/>
<xsl:variable name="n" select="floor((4 * $la) div 146097)"/>
<xsl:variable name="lb" select="$la - floor((146097 * $n + 3) div 4)"/>
<xsl:variable name="i" select="floor((4000 * ($lb + 1)) div 1461001)"/>
<xsl:variable name="lc" select="$lb - floor((1461 * $i) div 4) + 31"/>
<xsl:variable name="j" select="floor((80 * $lc) div 2447)"/>
<xsl:variable name="day" select="$lc - floor((2447 * $j) div 80)"/>
<xsl:variable name="ld" select="floor($j div 11)"/>
<xsl:variable name="month" select="$j + 2 - (12 * $ld)"/>
<xsl:variable name="year" select="100 * ($n - 49) + $i + $ld"/>
<!-- whole days -->
<xsl:variable name="iday" select="floor($day)"/>
<!-- pad final result -->
<xsl:variable name="sday" select="concat(substring('00',1,2 -
string-length(string($iday))),string($iday))"/>
<xsl:variable name="smonth" select="concat(substring('00',1,2 -
string-length(string($month))),string($month))"/>
<xsl:variable name="syear" select="concat(substring('00',1,4 -
string-length(string($year))),string($year))"/>
<!-- final output -->
<xsl:value-of select="concat($syear,'-',$smonth,'-',$sday)"/>
</xsl:template>

</xsl:stylesheet>

Cheers
Marrow
http://www.marrowsoft.com - home of Xselerator (XSLT IDE and debugger)
http://www.topxml.com/Xselerator
 
B

Bob Foster

Martin Boehm said:
Just estimated the PHP solution:
(I hold the difference between the power of your CPU and that of mine
for quite negligible, and the amount RAM does not matter here. I used a
for loop containing a call to the PGP date() function.)

My 1.8 GHz P4 with 512 MB of RAM (Win2k, too) did 1.000.000 conversions
in a 10 reiterations average of 7.57 seconds, this breaks down to about
132100 per second. For a single conversion that would be (quite exactly)
7,56998 * 10^-6 seconds, or ~0.076 milliseconds.

I am amazed. :)

I am, too. You did 1 million in 7.6 seconds and Dimitre did 104 thousand in
7.5 seconds, yet his is slightly faster per conversion! That is truly
amazing. But I believe 7.6 * 10^-6 seconds is 7.6 microseconds, which is
0.0076 milliseconds.

Bob Foster
 
D

Dimitre Novatchev

Just estimated the PHP solution:
(I hold the difference between the power of your CPU and that of mine
for quite negligible, and the amount RAM does not matter here. I used a
for loop containing a call to the PGP date() function.)

My 1.8 GHz P4 with 512 MB of RAM (Win2k, too) did 1.000.000 conversions
in a 10 reiterations average of 7.57 seconds, this breaks down to about
132100 per second. For a single conversion that would be (quite exactly)
7,56998 * 10^-6 seconds, or ~0.076 milliseconds.

I am amazed. :)

surrendering,

Martin

P.S.: Would you mind do post or mail the code you used so I can make a
direct comparison on that? Thanks!

Here it is -- just check (as I did) that the value of count($vNodes) is 104:

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

<xsl:import href="E:\Program
Files\Marrowsoft\Xselerator25\Samples\Libraries\datetime_lib.xsl"/>

<xsl:eek:utput method="text"/>

<xsl:variable name="vDaySecs" select="86400"/>

<xsl:template match="/">
<xsl:variable name="vNodes"
select="document('')//node() | document('')//@* |
document('')//namespace::*"/>

<xsl:variable name="vResult">
<xsl:for-each select="$vNodes">
<xsl:call-template name="unix-timestamp-to-datetime">
<xsl:with-param name="pTimeStamp" select="875996580"/>
</xsl:call-template>
</xsl:for-each>
</xsl:variable>
<!-- <xsl:value-of select="count($vNodes)"/>-->
</xsl:template>

<xsl:template name="unix-timestamp-to-datetime">
<xsl:param name="pTimeStamp" select="0"/>

<xsl:variable name="vBase">
<xsl:call-template name="date-to-julian-day">
<xsl:with-param name="date" select="'1970-01-01'"/>
</xsl:call-template>
</xsl:variable>

<xsl:call-template name="float-to-date-time">
<xsl:with-param name="value" select="$vBase + $pTimeStamp div
$vDaySecs"/>
</xsl:call-template>
</xsl:template>

</xsl:stylesheet>


P.S.
1. This solution can be optimized still more by having a constant for vBase
(2440588) and not calculating it every time. Then the result for 92
conversions is 3.776 milliseconds, which makes:

0.041 milliseconds for one conversion


24390 conversions per second.


2. This is not the first example of an efficient XSLT application. See my
article in xml.com "EXSLT for MSXML" at the end of which there is a
comparison table showing the timings of XSLT processors that implement the
Sets module of EXSLT.

The EXSLT implementation for MSXML4 was faster than 5 of them -- JD (Java),
4XSLT (Python), .Net xsltTransform (C#), xsltProc (C) and Xalan J 2.4.1
(Java).

For those, who don't know -- the (Sets module of) EXSLT support for MSXML4
is implemented in XSLT.

So, in this case the XSLT implementation outperforms implementations written
in such languages as C, C#, Java and Python.


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top