RE: [xsl] XSLT transformation flow based upon data type (access s chema from within XSLT?)

Subject: RE: [xsl] XSLT transformation flow based upon data type (access s chema from within XSLT?)
From: Adam Griffin <agriffin@xxxxxxxxxxxx>
Date: Sat, 19 Oct 2002 15:00:32 -0400
Sorry for double post. Accidentally keyed Ctrl-Enter and sent it on its way
(i'm all thumbs today). The rest of the post is below.

Much thanks Jeni, Dion, Michael.

I should have said XPath instead of XSLT (I always forget to separate XPath
out of XSLT), but you guys seemed to steer me in the right direction anyway.
The current project regulates MSXML (v4) parser so the MS extensions will
work just fine in this case. I took a look at the XPath2.0wd and it does
address extensive tie-in with schema. It looks like the xquery-typeof
function is going to be similar to ms:type-local-name function?



Jeni, you requested a write up for what I thought it should work...

What I am making is a XSLT doc to handle "generic" XML docs reflecting a
table structure looking something like:
<NewDataSet>
  <Table1>
    <Data1>A</Data1>
    <Data2>B</Data2>
    <Data3>C</Data3>
  </Table1>
  <Table1>
    <Data1>D</Data1>
    <Data2>E</Data2>
    <Data3>F</Data3>
  </Table1>
</NewDataSet>

The XML docs will always have these 3 levels, and a proper schema
validation, but the element names are subject to change. Different table,
different data, and different amounts of data are possible. Rather than make
one style sheet for every table, I'd much rather make one to serve most
scenarios. Text, numbers and dates all need their own formatted HTML
presentation. If i can get the type, then I can apply the proper formatting
template and display most tables in one common format and manage the format
from there.

============================
My first working version is:
============================
<xsl:template match="/">
	<table>
		<xsl:apply-templates select="/*/*" />
	</table>
</xsl:template>

<!-- match only those nodes having children having text --> 
<xsl:template match="*[*[text()]]">
	<tr>
		<xsl:apply-templates select="*"/>
	</tr>
</xsl:template>

<xsl:template match="*[msxsl:type-local-name(.)='string']">
	<td>str ~ <xsl:value-of select="."/></td>
</xsl:template>
<xsl:template match="*[msxsl:type-local-name(.)='dateTime']">
	<td>date ~ <xsl:value-of select="."/></td>
</xsl:template>
<xsl:template match="*[msxsl:type-local-name(.)='unsignedByte']">
	<td>unsignedByte ~ <xsl:value-of select="."/></td>
</xsl:template>
<xsl:template match="*">
	<td>otherwise ~ <xsl:value-of select="."/></td>
</xsl:template>

============================
My second working version is:
============================
<xsl:template match="/">
	<table>
		<xsl:apply-templates select="/*/*" />
	</table>
</xsl:template>

<xsl:template match="*">
	<tr>
		<xsl:for-each select="*">
		<xsl:choose>
			<xsl:when test="msxsl:type-local-name(.)='string'">
				<td>str ~ <xsl:value-of select="."/></td>
			</xsl:when>
			<xsl:when
test="msxsl:type-local-name(.)='dateTime'">
				<td>date ~ <xsl:value-of select="."/></td>
			</xsl:when>
			<xsl:when
test="msxsl:type-local-name(.)='unsignedByte'">
				<td>unsignedByte ~ <xsl:value-of
select="."/></td>
			</xsl:when>
			<xsl:otherwise>
				<td>otherwise ~ <xsl:value-of
select="."/></td>
			</xsl:otherwise>
		</xsl:choose>
		</xsl:for-each>
	</tr>
</xsl:template>

============================
interesting side note using a crude timer:

    var dStart = new Date();
    TransDOM(domXML,domXSL);
    var dStop = new Date();
    divState.innerText = (dStop-dStart)/1000;

First Second (in seconds)
3.296 1.969
4.547 2.25
3.813 2.5
4.265 2.391
3.875 2.344

The first version took roughly twice as long to process as the second one
(using MSXML ver 4 DOMs). I would have thought the templates would have
worked faster? Did I utilized proper/efficient pattern matching on the
first?



 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread