May 2004 - Posts

Embeddng XML in an XSLT in .NET

I have a XSLT that needs to reference a table of data, such as states.  This data is very static, so it didn't seem to be worth the trouble to store this data in a table and pass it in as a node set.  (See one my previous posts for an example of this.)  I decided to embed this data as an XML “data island” in my XSLT and reference it via an XSLT variable.  This is pretty standard stuff, but I couldn't get it to work. 

I consulted my copy of XSLT and XPath On The Edge, by Jeni Tennison, and found that I was doing everything correctly.  It still didn't work, so what was wrong?

.NET was the problem.  In the 1.1 version of the framework, the transform method has a fourth argument, which is for a resolver.  I've always passed null (or nothing) here, and everything worked well.  When using the XSLT document() function, however, the resolver becomes important.  Without a resolver, the document function is ignored.  Examine the working code:

XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:st="http://www.mysite.com/States">
     
<xsl:output method="xml" indent="yes" />

      <st:States>
           
<st:State Code="AL" Name="Alabama"/>
           
<st:State Code="MS" Name="Mississippi"/>
           
<st:State Code="TN" Name="Tennessee"/>
     
</st:States>

      <xsl:variable name="VisaCodes" select="document('')//st:States/st:State"/>
</
xsl:stylesheet>

.NET
myTransform.Transform(myXPathDoc, myArgumentList, OutputFile, new XmlUrlResolver());

Convert .NET-compatible ticks to a SQL DateTime value

I've been storing dates in SQL server, not as actual DateTime values, but as 100-nanosecond ticks using the BIGINT data-type.  (Don't ask why; I have some really weird program requirements.)  Up until recently, this caused no real issues, because .NET can easily handle the conversion.  However, due to a scope change, I now have to create a Stored Procedure that does this conversion.  So, how does one convert from .NET ticks to a SQL DateTime?  Here ya go:

CREATE FUNCTION dbo.udfTicksToDateTime
(
      @Ticks BIGINT
)
RETURNS DATETIME
AS
BEGIN
      DECLARE
@Days  BIGINT
      DECLARE
@DaysBefore1753 BIGINT
      DECLARE
@TimeTicks BIGINT
      DECLARE
@Seconds BIGINT

      SET @Days = @Ticks / CONVERT(BIGINT,864000000000)
      SET @DaysBefore1753 = CONVERT(BIGINT,639905)
      SET @TimeTicks = @Ticks % CONVERT(BIGINT,864000000000)
      SET @Seconds = @TimeTicks / CONVERT(BIGINT,10000000)

      RETURN DATEADD(s,@Seconds,DATEADD(d,@Days - @DaysBefore1753,CONVERT(DATETIME,'1/1/1753')))
END

Pass an XML node set to XSLT from .NET

I recently needed to pass some XML into my XSLT before performing a transform.  Normally, this isn't very useful, because the XML gets converted into a string, not a node set.  However, .NET provides a way around this problem.  Because it took quite a while to discover the method, I thought I would note it here.

.NET Snippet
// create an XsltArgumentList to contain the node set
myArgumentList = new XsltArgumentList();

// load the nodes
NodeDoc = new XmlDocument();
NodeDoc.LoadXml(<Place XML here>);

// create a navigator, so that an iterator can be created
NodeNav = NodeDoc.CreateNavigator();
NodeItr = NodeNav.Select("/Parent/Child");

// populate argument list
myArgumentList.AddParam("NodeInfo", "", NodeItr);

// transform the XML directly to the file
myTransform.Transform(myXPathDoc, myArgumentList, OutputFile, new XmlUrlResolver());

XSLT Snippet
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:vc="http://www.me.com/Codes">
<xsl:param name="NodeInfo" select="/.."/>

<xsl:template match="/">
     
<xsl:for-each select="$NodeInfo">
            .
..
      </xsl:for-each>
</xsl:stylesheet>

St. Louis Security Summit

Yes, another Security Summit.  As always, I learned some new tricks, even while teaching the attendees.  My favorite was while running a demo on one of my VPCs.  The keyboard completely locked up, and nothing I did could correct this.  (Having your PC lock up during a demo, in front of hundreds of people, is not a good feeling.)  One of the attendees asked me to try pressing the left control key.  I did, and the keyboard started working again.  I will definitely remember this little trick.

As always, I want to thank a couple of the attendees for their participation.  You know who you are!  I really prefer leading a discussion group, rather than a simple lecture.  Pratical experience beats rote knowlege every time!