July 2007 Archives

That's cool URL. http://www.microsoft.com/opensource I mean. The announcement at port25 site goes like this:

Today, Microsoft took another step in its relationship with the open source software community. We did this by bringing up a new web property that clearly outlines Microsoft’s position on OSS by providing specific information about Microsoft, the OSS community and the interaction between the two. The new site also details information about getting started with OSS and Microsoft technologies.  We'll keep the site updated with new content featuring Microsoft’s engagements with the OSS community - be that events like OSCON, partnerships, offers or just interesting articles highlighting different work we're doing across the company. Port 25 will continue to be the source for technical analysis and community with the Open Source Software Lab.

And of course it has a link to the John Lam's IronRuby announcement right on the front page.

There is even "Open Source at Microsoft" feed, consisting mostly of case studies, for those interested.

 John Lam announced the very first pre-alpha drop of IronRuby - Microsoft open source (!) implementation of the Ruby language, licensed under Microsoft Permissive License. This release contains early bits of Ruby implementation for .NET based on the DLR(Dynamic Language Runtime), you actually have to build it if you want to run it. Scott Guthrie shows command line and WPF hello-world sample apps built with IronRuby.

IronRuby team takes unique (for Microsoft) approach - not only IronRuby implementation is going to be open source (IronPython is open source already), they actually plan to host it on RubyForge and accept source code contributions:

IronRuby Project Plans

Next month we will be moving the IronRuby source code repository to be hosted on RubyForge.  As part of this move we are also opening up the project to enable non-Microsoft developers to enlist in the project and contribute source code. We'll then work to implement the remaining features and fix compatibility issues found as more libraries and source are ported to run on top of it. 

The end result will be a compatible, fast, and flexible Ruby implementation on top of .NET that anyone can use for free.

Unbelievable. Either Microsoft don't see any money behind IronRuby or this is some kind of evil experiment.

I love Ruby and .NET. Sure I will be contributing.

Btw, don't be confused with IronRuby and Ruby.NET projects. IronRuby is new Microsoft Ruby implementation, while Ruby.NET is soon-to-be-open-source Ruby implementation started by Queensland University in Australia. While IronRuby uses parts of Ruby.NET compiler, John Lam sees IronRuby as continuation of the Ruby.NET. Both projects seem to be similar and so I believe Ruby.NET story is probably over.

I'm playing with IronRuby right now. This is cool stuff, now I want it to be fast, I want full Visual Studio support and I want it to be my primary language. Screw Java and C#, Ruby is where all fun is.

And finally another great news about Visual Studio 2008 from Scott Guthrie:

You'll see Beta2 ship later this week - so only a few more days now.

It's known that .NET XSLT engine - XslCompiledTransform natively supports two EXSLT extension functions - exsl:node-set() and exsl:object-type(). Not that it's widely known (msdn still says nothing about it), but lots of people are using this handy feature. The main benefit is that using EXSLT's version of node-set() function allows complex XSLT stylesheets (and I guess 80% of complex stylesheets can't live without xxx:node-set() function) to be portable between .NET, Java and libxslt.

Now, let's admit this fact is very little known.  I've seen even advanced XSLT developers still using annoying techniques like switching "http://exslt.org/common" and "urn:schemas-microsoft-com:xslt" namespaces or awkward xsl:choose "function-available('exslt:node-set')" blocks. That's wrong.

These days you don't need any special handling for EXSLT exsl:node-set() function in your server-side oriented XSLT stylesheets. Just use it. .NET, Java and libxslt all support it.

I think (.NET and MSXML)-only msxsl:node-set() function should be avoided. Unless you are targeting browsers (in which case you need this trick).

I found it useful to insert EXSLT common namespace declaration into Visual Studio templates for XSLT files. It works as a reminder and is just handy. Here is how you can do it. Open XSLT templates for "Add new item" and "New File" commands:

  1. C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\ItemTemplatesCache\CSharp\1033\XSLTFile.zip\XSLTFile.xslt
  2. C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\ItemTemplatesCache\VisualBasic\1033\XSLTFile.zip\XSLTFile.xslt
  3. C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\NewFileItems\xsltfile.xslt

and add xmlns:exsl="http://exslt.org/common" and exclude-result-prefixes="exsl" to the xsl:stylesheet element:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl">

Total loss

| 4 Comments | No TrackBacks |

I've been in a car accident a week ago. First time ever. The car is totaled, but I'm totally fine, just a couple of scratches. Happily I was alone and was driving slowly enough.

That's been interesting experience though, but not that I wish to anybody to have. Kind of "driving the very right lane, nobody ahead of me, life is perfect, music is great, BOOM!, totally new reality". As it turned out there was another car accident on the left line just a second before and one car bounced off to my line literally a meter before me. What's amazing is that no matter how hard I try I can't recall a moment when there is another car before mine. All I remember is empty line and then airbag. How come? Is it eyes or brains limitation or was I just looking somewhere else at the moment? Or may be my brain doesn't want me to remember such shocking moments? That's sort of disappointing, like been in a car accident, but haven't seen anything.

Anyway, again, I'm totally ok.

Producing XHTML using XSLT 1.0 processor is tough (no wonder - XSLT 1.0 is so old - it was published even before XHTML 1.0). While XHTML is just XML, XHTML spec defines a set of very specific formatting rules called "HTML Compatibility Guidelines". The goal is to facilitate rendering of XHTML by HTML browsers (such as Internet Explorer :).

The guidelines say for instance that elements with non-empty content model (such as <p>) must never be serialized in minimized form (<p />), while elements with empty content model (such as <br>) must never be serialized in full form (<br></br>).

While XML doesn't care about such nonsense, HTML browsers might be confused and so XHTML generation should be smart enough. And XSLT 1.0 processors can only output text, HTML or XML (XSLT 2.0 processors can also do XHTML). That's why generating XHTML using XSLT 1.0 processor is tough.

I implemented one simple solution to the problem in the Mvp.Xml library 2.3. Here is a sample that says it all:

XSLT stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" 
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
    doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"/>
  <xsl:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml">
      <head>
        <title/>
      </head>
      <body>
        <p>Para element must have end tag even if empty:</p>
        <p/>
        <p>These elements must not have end tags:</p>
	<p>
          <br></br>
          <hr></hr>
          <img src="foo.jpg" alt="bar"></img>
        </p>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

The code:

using System;
using System.Xml.XPath;
using System.IO;
using Mvp.Xml.Common.Xsl;

class Program
{
  static void Main(string[] args)
  {
    XPathDocument doc = new XPathDocument(
      new StringReader(""));
    MvpXslTransform xslt = new MvpXslTransform();
    xslt.Load("../../XSLTFile1.xslt");
    xslt.EnforceXHTMLOutput = true;
    xslt.Transform(new XmlInput(doc), null, 
      new XmlOutput(Console.Out));
  }
}

The result:

<?xml version="1.0" encoding="DOS-862"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title></title>
  </head>
  <body>
    <p>Para element must have end tag even if empty:</p>
    <p></p>
    <p>These elements must not have end tags:</p>
    <p>
      <br />
      <hr />
      <img src="foo.jpg" alt="bar" />
    </p>
  </body>
</html>

If for some weird reason you don't want to use MvpXslTransform class, you can stay with XslCompiledTransform and just output via XhtmlWriter class:

using System;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.Xml;
using System.IO;
using Mvp.Xml.Common;

class Program
{
  static void Main(string[] args)
  {
    XPathDocument doc = new XPathDocument(
      new StringReader(""));
    XslCompiledTransform xslt = new XslCompiledTransform();
    xslt.Load("../../XSLTFile1.xslt");            
    xslt.Transform(doc, null, 
      new XhtmlWriter(
        XmlWriter.Create(Console.Out, xslt.OutputSettings)));
  }
}

Saxon, NET and XInclude

| 4 Comments | 1 TrackBack | , ,

Saxon, famous XSLT 2.0 and XQuery processor, supports XInclude since version 8.9. But in Java version only! When I first heard about it I thought "I have good XInclude implementation for .NET in Mvp.Xml library, let's check out if Saxon on .NET works with XInclude.NET". I did some testing only to find out that they didn't play well together. 

Turned out Saxon (or JAXP port to .NET, don't remember) relies on somewhat rarely used in .NET XmlReader.GetAttribute(int) method (yes, accessing attribute by index), and XIncludingReader had a bug in this method.

Finally I fixed it and so XIncludingReader from recently released Mvp.Xml library v2.3 works fine with Saxon on .NET.

Here is a little sample how to process XML Inclusions in source XML document before XSLT transformation.

using System;
using Saxon.Api;
using Mvp.Xml.XInclude;

class Program
{
  static void Main(string[] args)
  {
    Processor proc = new Processor();
    XdmNode doc = proc.NewDocumentBuilder().Build(
      new XIncludingReader("d:/test/document.xml"));
    XsltExecutable xslt = proc.NewXsltCompiler().Compile(
      new Uri("d:/test/foo.xsl"));
    XsltTransformer trans = xslt.Load();
    trans.InitialContextNode = doc;
    Serializer ser = new Serializer();
    ser.SetOutputStream(Console.OpenStandardOutput());
    trans.Run(ser);            
  }
}

I released version 2.3 of the Mvp.Xml Library, which is part of the Mvp.Xml Project developed by Microsoft MVPs in XML technologies worldwide. It is aimed at supplementing .NET framework XML processing functionality. Mvp.Xml Library provides .NET implementations of the EXSLT, XML Base, XInclude, XPointer as well as a unique set of utility classes and tools making XML programming in .NET platform easier, more productive and effective.

This is another minor release of the Mvp.Xml Library for .NET 2.0.
Version 2.3 fixes lots of bugs and introduces some new features.
Most important new features include:

  • XHTML output mode for the MvpXslTransform class
  • XSLT2-like output character mapping for the MvpXslTransform class
  • XmlWrappingReader and XmlWrappingWriter to simplify creating of custom XmlReader or XmlWriter
  • XIncludingReader now implements IXmlLineInfo interface
  • MvpXslTransform.AddExsltExtensionObjects() method allows to add EXSLT extension functions to your XsltArgumentList instance
  • XIncludingReader.Encoding property
  • New Mvp.Xml Library API documentation site generated using Sandcastle/DocProject, hosted at http://www.xmllab.net/mvpxml

Most important bugs fixed:
  • XIncludingReader now works well with Saxon.NET, XmlSerializer, DataSet and others
  • Library DLL is now debuggable
  • No more XmlValidatingReader and XmlTextReader used


Find detailed list of new features and bug fixes and download it at the Mvp.Xml v2.3 release page.

Mvp.Xml Library is free open-source (BSD-style).

I'll post about new features more thoroughly this week. Enjoy.