Here is a small quick release. IronXSLT v0.3.
New in this version:
- IronXSLT installer turns on dynamic XSLT Intellisense
- Improved compatibility with Visual Studio 2008
Oleg Tkachenko's Blog
|
Recently in XSLT CategoryHere is a small quick release. IronXSLT v0.3. New in this version:
A very little known fact is that Visual Studio 2008 does support real XSLT intellisense - not a static XSLT schema-based one, but real dynamic intellisense enabling autocompletion of template names, modes, parameter/variable names, attribute set names, namespace prefixes etc. For some obscure reason it is off by default and obviously completely undocumented. I'll show you how to turn it on. But before - a little teaser. 1. When you about to call a named template you are presented with a list of all named templates in your stylesheet. My favorite feature. Finally you don't have to remember all your template names: 2. In XSLT template parameters are passed by name, so when you call a template and want to pass parameters you actually have to know exactly what parameter names are. And you better know them for sure, because if you make a mistake you pass a parameter with wrong name you get no error or even warning. XSLT 1.0 specification allows such nonsense. That's why template parameter name autocompletion is a real time saver: 3. You can pass parameters when applying templates too. Obviously due to dynamic XSLT processing model it's hard to know in advance which template will be matched at run time, so it's hard to suggest list of parameter names. In this version of XSLT intellisense we get list of all parameters used in all templates, filtered by mode. I believe XML Tools could optimize it a bit by filtering the list when it's clear from the context which template will be matched. Anyway, very useful: 4. Autocompletion of template modes is also extremely useful. Make mistake in mode name and you can spend hours in debugger trying to figure out why your template isn't matched, because again this is not an error or even something wrong according to XSLT spec. That's why this is so cool: 5. Finally a couple of useful namespace prefix autocompletions. exclude-result-prefixes now becomes easier: and <xsl:namespace-alias> (mostly used for generating XSLT using XSLT):6. If you use <xsl:attribute-set> elements, you will be happy to see this one:
These are autocompletions I'm currently aware of. There might be more - it's currently completely undocumented and I probably the first one writing about this feature. For example key names are collected too, but I haven't found where they are used. If you happen to discover another XSLT autocompletion, report it in comments section please. And finally how to turn this awesomeness on: Yes, regedit. Create String value called "XsltIntellisense" under "HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\XmlEditor" key. "True"/"False" are valid values. If you are too lazy for editing registry manually, here is XsltIntellisense.reg file you can run (but rename it to .reg before). If you don't want to mess with registry, wait till tomorrow. I'm going to release IronXSLT v0.3, which will turn XSLT intellisense on for you while installing. Enjoy! Here is another interesting problem: how do you generate HTML excerpts preserving HTML structure and style? Say you have long XHTML text: <b>This is a <span style="color: #888">very long</span> text.</b> In browser it looks like this: This is a very long text. The text is 25 characters long. Now you need to generate a short excerpt - cut it down to 15 characters, while preserving HTML structure and style: <b>This is a <span style="color: #888">very ...</span></b> So in a browser it would look like This is a very ... I solved it in XSLT 1.0 using ugly (but effifcient) recursive template: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:param name="max-len" select="15"/> <xsl:template match="/"> <xsl:call-template name="trim"/> </xsl:template> <xsl:template name="trim"> <xsl:param name="rlen" select="0"/> <xsl:param name="nodes" select="*"/> <xsl:choose> <xsl:when test="$rlen + string-length($nodes[1]) <= $max-len"> <xsl:copy-of select="$nodes[1]"/> <xsl:if test="$nodes[2]"> <xsl:call-template name="trim"> <xsl:with-param name="rlen" select="$rlen + string-length($nodes[1]) "/> <xsl:with-param name="nodes" select="$nodes[position() != 1]|$nodes[1]/*"/> </xsl:call-template> </xsl:if> </xsl:when> <xsl:when test="$nodes[1]/self::text()"> <xsl:value-of select="substring($nodes[1], 1, $max-len - $rlen)"/> <xsl:text>...</xsl:text> </xsl:when> <xsl:otherwise> <xsl:if test="$nodes[1]/node()"> <xsl:element name="{name($nodes[1])}" namespace="{namespace-uri($nodes[1])}"> <xsl:copy-of select="$nodes[1]/@*"/> <xsl:call-template name="trim"> <xsl:with-param name="rlen" select="$rlen"/> <xsl:with-param name="nodes" select="$nodes[1]/node()"/> </xsl:call-template> </xsl:element> </xsl:if> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> But I'm not happy with this solution. There must be more elegant way. The problem just smells FXSL. Hopefully Dimitre can show me how FXSL can do it with beauty and style. I also wonder how would you do it with XLinq? We are working on yet another language migration tool and faced once again Java source code generation problem. Unfortunately Java doesn't have anything similar to .NET's CodeDOM, so we had to build own own Java generator. This time our development platform is XSLT 2.0. Yes, we are converting COOL:Gen (obscure 4GL model-based language) to Java using XSLT 2.0. XSLT 2.0 rocks by the way. This is first time I write production code in XSLT 2.0 and this is amazing experience. Suddenly all is so easy, everything is possible, no hassle. Despite poor authoring support (Eclipse XSLT editor sucks, while Visual Studio 2008 with XSLT 2.0 schema is ok, but cannot run Saxon), lack of debugger and Saxon quirks I had a blast practicing XSLT 2.0 for real. At first I started generating Java beans simple way: output mode="text" and producing Java sources as text. Obviously it sucked big way. I spent a week and got it done, but with way too cumbersome and fragile code. Generating code and simultaneously coping with Java syntax and formatting is hard. Additional layer of indirection was needed desperately. One of smart guys I work with came with a simple but brilliant idea. Vladimir took Java 6 ANTLR grammar and converted it to XML Schema. Then he developed a generic serializer (also in XSLT 2.0 of course) that is able to convert XML document confirming to Java XML schema (he called it JXOM - Java XML Object Model) into nicely formatted and optimized decent Java 6 source code. Then I rebuilt my Java bean generator using JXOM instead in just one day. Building Java as XML is so much easier and cleaner, I believe it's even easier than using System.CodeDom in .NET (obviously CodeDom can do more than just generate C# or VB sources). Anyway, anybody interested in Java generation - check out JXOM. This is really easy way to generate Java 9even Java 6.0) using XSLT. It's freely available and it just works. Here are more links: JXOM is ready to use, but still under active development. Any feedback is highly appreciated at Vladimir and Arthur Nesterovsky blog. Sergey Dubinets, the guy behind Microsoft XSLT engine and tools is blogging. Subscribed. Highly recommended. More XSLT bloggers from Microsoft: Inspired by ioccc.org, just for fun, really. Can you figure out what this stylesheet outputs (without running it of course)? <!DOCTYPE p [ <!ENTITY _0_ 'string'> <!ENTITY _0-0_ 'sub&_0_;'> ]> <p x:version="1.0" xmlns:x="http://www.w3.org/1999/XSL/Transform"> <x:variable name="_" select="document('')"/> <x:variable name="_-_" select="number(not(_-_=_-_=_-_=_-_))"/> <x:value-of select="concat( &_0-0_;(namespace-uri($_/*/*[$_-_]), $_-_, $_-_), &_0-0_;(name($_/*/*[$_-_]), &_0_;-length(*>*)*2, $_-_), &_0-0_;(@_>_-, &_0_;-length(******* div @_), $_-_), translate(name(($_//@*)[5]), translate(name(($_//@*)[5]), 'l', ''), ''), &_0-0_;($_//namespace::*, &_0_;-length($_-_ div 0)+7, $_-_), ' ', &_0-0_;-after(&_0-0_;-before($_//namespace::*, 3), '.'), &_0-0_;($_//namespace::*, 15, 2), &_0-0_;(_/_/_=//_//_, 3, $_-_), &_0-0_;($_/*/*/@*[contains(.,'(')], $_-_, $_-_), '!')"/> </p> By the way, does anybody think XSLT obfuscator is a useful tool? Microsoft XML Tools team has released XSLT profiler addin for Visual Studio 2008. I've heard about this tool and even did a little testing long time ago (apparently it's very hard to release anything in Microsoft). First thing you need to know about Microsoft XSLT profiler - it requires Visual Studio 2008 Team System edition with the Performance Tools feature installed. That actually sounds a bit steep for just XSLT profiler, but it starts to make sense once you realize this tool is just a thin wrapper around the F1 profiler (which only ships with Visual Studio Team System SKU). Once installed, it adds "Profile XSLT" command (visible only in XSLT context, i.e. when active document is XSLT stylesheet) to the XML menu:
Before you see profiling results you should recall that XSLT in .NET starting with 2.0 is compiled to MSIL:
As you can see, an XSLT stylesheet is being compiled into a class and each template becomes a method with cool special name like <xsl:template match="book">. That was smart. And yes, MSIL is completely ok with such kind of method names. Beside template-mehods the generated class contains other auxiliary stuff. So don't be surprised with XSLT profiling results:
I'd say there is too much clutter in this form. I'd like to see only XSLT relevant info, but as you can understand now, it's the the results of profiling compiled assembly and XSLT part is here only because smart compilation tricks. Still extremely useful tool. A must for anybody writing XSLT in Visual Studio. Besides Summary View there are: Call Tree View, Modules View, Caller/Callee, Functions, Marks and Processes Views. You can find more info about profiling report details at http://code.msdn.microsoft.com/xsltprofiler. I'd be happy to see next version. With all clutter removed, more XSLT focused, linked to XSLT source (seems like currently there is no way to get back to template source from report), may be with some smart visualizations (what about coloring XSLT source view to indicate the hot spots?). Oh well, provided it took XML Tools team so long to ship this tool I better try to implement all these ideas myself in Iron XSLT (stay tuned, it's not dead as I'm back). When you create new XSLT stylesheet in Visual Studio via project (Add/New Item) or globally (File/New/File aka Ctrl+N), you start with template content. This template is changing in every new Visual Studio version, probably because every new generation of developers working on XSLT tools in Visual Studio have different vision about what you should start with. Let's see. Visual Studio 2003. Pure simplicity: <?xml version="1.0" encoding="UTF-8" ?> <stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform"> </stylesheet> Visual Studio 2005 has two different templates for new XSLT stylesheet (!). When you create it via project you get the same as above empty stylesheet template. But if you go via Ctrl+N you get this fancy template: <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" exclude-result-prefixes="exsl"> <xsl:template match="/"> <html> <body> <!-- This is an XSLT template file. Fill in this area with the XSL elements which will transform your XML to XHTML. --> </body> </html> </xsl:template> </xsl:stylesheet> Yes, believe it or not, but some Microsoft developers were sure you should start with EXSLT namespace declaration in your stylesheet. The fact is that .NET 2.0 introduced partial native support for EXSLT, but it was never documented. It's still hidden portability gem. Now what you get in Visual Studio 2008: <?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" > <xsl:output method="xml" indent="yes"/> <xsl:template match="@* | node()"> <xsl:copy> <xsl:apply-templates select="@* | node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet> No more EXSLT, back to basics - proprietary nonportable MSXSL namespace by default. This is sad. Beside this weird proprietary comeback it's interesting that this new template contains identity transformation rule. This cumbersome looking <xsl:template> is the base of data transformation filtering. It processes every single node in source document recursively and outputs it as is. By adding more template rules you can override base behavior to add, remove or modify particular nodes. Very powerful technique. This is smart choice for new file template. State of the art of XSLT testing in a simple succinct format by Tony Graham.
I noticed Robert Robbins was writing about XSS attacks using XSLT:
Well, that's not exactly true, at least on Microsoft platform. Microsoft tackled this issue long time ago. Both MSXML 6.0 and .NET (since 2.0) don't allow script extensions and document() function in XSLT by default. One has to enable them explicitly. So the truth is s bit different: any web application that allows the user to upload their own XSL file and explicitly allows executing embedded scripts will be vulnerable to Cross Site Scripting attacks. While we at this, here is some refresher for this important to know topic:
XslCompiledTransform Security:
Better later than never. I uploaded IronXSLT 0.2 release. New in this version:
My goal was to make F5/Ctrl+F5 working intuitively right - when you work on XSLT Library project F5 should run project with debugger and Ctrl+F5 - without. When you have more that one stylesheet it's nice time saving feature, not to mention that start debugging command finally starts debugger as it should. But what to run? So I introduced a notion of a startup XSLT stylesheet in a project. It's kinda like startup object in C# projects, but currently only affects debugging within Visual Studio. You mark your startup stylesheet either via project properties (Debug tab): or via new context menu item I added to XSLT stylesheets: Once you have startup stylesheet in XSLT Library project you can start it as you usually start project with or without debugging: I also spent unbelievable amount of time trying to make startup stylesheet bolded in Solution Explorer. It still doesn't work on project load... Anyway, get IronXSLT 0.2 at http://www.xmllab.net/downloads. It's free. Give it a try with Visual Studio 2008 Beta2. Find more documentation at http://xmllab.net/ironxslt. Here goes nxslt3.exe/NxsltTask v3.0. It's nxslt tool for .Net 3.5. It can do everything nxslt2/NxsltTask v2.3 can plus the ability to run compiled XSLT stylesheets. Now short documentation about running compiled XSLT stylesheets. Let's say you have a stylesheet called mytransform.xsl. First you compile it using nxsltc: nxsltc mytransform.xsl /out:mytransform.dll The result is mytransform.dll, containing mytransform class. Now you can run it. Here is a full form: nxslt3 document.xml -c mytransform -af mytransform.dll -c option says you want to run compiled stylesheet. Instead of XSLT stylesheet file name you pass compiled stylesheet class name (fully qualified if it has a namespace). And you need to specify dll file, where compiled stylesheet can be found. Of course if you can afford assume things you can make it shorter. If dll is named after stylesheet and can be found in the current directory, you can omit it: nxslt3 document.xml -c mytransform Alternatively if dll contains single compiled stylesheet you can specify dll and omit stylesheet: nxslt3 document.xml -c -af mytransform.dll If you happens to compile your stylesheets into a strongly named dll: nxsltc mytransform.xsl /keyfile:d:\keys\test.snk and then installed it into the GAC, you run it by specifying full or partial dll name after -an option: nxslt3 document.xml -c -an "mytransform, Version=1.0.0.0, PublicKeyToken=b79508ebff528747" This works too (partial name): nxslt3 document.xml -c -an mytransform That's about it. And finally. nxslt3 is a free feature-rich .NET 3.5 XSLT command line utility and NAnt/MSBuild task which uses .NET XSLT processor - XslCompiledTransform class and supports XML Base, XInclude, XPointer, EXSLT, compiled stylesheets, embedded stylesheets, processing instruction, multioutput, custom URI resolving, custom extension functions, pretty printing, XHTML output, XSLT 2.0-like character maps and more. nxslt3.exe/NxsltTask are free tools under BSD license. Download here. I updated nxsltc - XSLT compiler for .NET 3.5 tool one more time. I added /version:<x.x.x.x> and /keyfile:<file> options. Former is used to specify resulting DLL version and latter - to sign it with a strong name. nxsltc.exe catalog2html.xslt /version:2.3.4.5 /keyfile:d:\keys\test.snk The usage now looks like this: D:\>nxsltc.exe /? XSLT Compiler version 1.0beta2 for .NET 3.5 (c) 2007 Oleg Tkachenko, http://www.xmllab.net Usage: nxsltc I also put together some documentation point at http://www.xmllab.net/nxsltc. I also updated nxsltc.exe (well, just rebuilt it using Visual Studio 2008 Beta2). nXSLTC is an experimental XSLT to MSIL compiler for the forthcoming .NET 3.5. nXSLTC compiles one or more XSLT stylesheets into DLL. Compiled stylesheets then can be used for transforming XML documents using XslCompiledTransform class. Now I have to compile nxslt for .NET 3.5 and make it able to run compiled stylesheets. Then I'm going to push IronXSLT. What's the probability of having two car accidents in one month? It must be high enough. Just a month after the first one some asshole hit me and run away. I wonder if it's a bad luck or actually a good luck? Sure, my own car is totaled and a company car doesn't look good either, but hey, I didn't get even a scratch, so I believe I'm a lucky guy. Ok, back to work. I uploaded version 2.3 of the nxslt2.exe/NxsltTask tool. It's probably the last version for .NET 2.0. Anyway, here is what's new: Oh, just in case: nxslt2 is a free feature-rich .NET 2.0 XSLT command line utility and NAnt/MSBuild task which uses .NET 2.0 XSLT processor - XslCompiledTransform class and supports XML Base, XInclude, XPointer, EXSLT, embedded stylesheets, processing instruction, multioutput, custom URI resolving, custom extension functions, pretty printing, XHTML output, XSLT 2.0-like character maps and more. nxslt2.exe/NxsltTask are free tools under BSD license. Download here. 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:
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"> 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(" 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(" 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.
Most important bugs fixed:
Mvp.Xml Library is free open-source (BSD-style). I'll post about new features more thoroughly this week. Enjoy. I found this gem in David Carlisle's blog. Smart Javascript trick allows to mask msxsl:node-set() extension function as exsl:node-set() and so you can easily write crossbrowser XSLT stylesheets using exsl:node-set() functionality. Opera 9, Internet Explorer 6-7 and Firefox 3 are covered, but sadly Firefox 2 is out of the game. Julian Reschke came with a nice trick using Javascript expressiveness: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="exslt msxsl"> <msxsl:script language="JScript" implements-prefix="exslt"> this['node-set'] = function (x) { return x; } </msxsl:script> ... Very smart. That reminds me old days of mine when I came with a similar trick for EXSLT extension functions implemented in C# (for EXSLT.NET project). Except that C# isn't so dynamic as Javascript so I had to escape to renaming method names in MSIL bytecode. That trick still drives EXSLT.NET (now module of the Mvp.Xml library). By the way just to remind you - .NET (XslCompiledTransform) supports exsl:node-set() function natively. Yes, I'm trying to change the way you work with XSLT in Microsoft Visual Studio. It must be a pleasure to develop and rocket fast at runtime. Yes, Visual Studio already supports editing, running and even debugging XSLT, but it's still a painfully limited support. So I'm started building IronXSLT - Visual Studio plugin aimed to provide total integration of the XSLT language in Visual Studio IDE. Current list of planned and already implemented IronXSLT features includes:
IronXSLT version 0.1 implements first point. IronXSLT supports only forthcoming Microsoft Visual Studio version, codenamed "Orcas", which is about to be released later this year. That also makes IronXSLT ship date. IronXSLT is free for personal and commercial usage, but not open source currently.
Continue reading IronXSLT: Changing the Way You Work with XSLT in Visual Studio.
I was reading Scott's post on Reflector Addins and had this idea... Now (well, not now but in the next .NET version - Orcas) that XSLT can be compiled into dll, it must be time to think about XSLT decompiler (and appropriate Reflector addin of course). I believe that must be feasible. Would it be useful for you?
To be continued... David Carlisle and Jeni Tennison are blogging. Skies are falling. Enough said. Subscribed. I mean pre-XProc XSLT pipeline - just when you need to transform an XML document by a sequence of XSLT stylesheets - output from the first transformation goes as input to the second one and so on. This is useful technique helping dramatically simplify your complex multi-stage XSLT stylesheets. Unfortunately there is no simple way to perform such task effectively in .NET 2.0. Here I show you how Mvp.Xml project comes to the rescue. Note: there is old crappy Microsoft KB article 320847 suggesting pipelining XSLT via byte buffer, Bleh!, don't do this. The problem is that while the most efficient (fastest, taking less memory) XML store for doing XSLT transformations in .NET 2.0 is still old good XPathDocument (not surprisingly specially designed and optimized for XPath and XSLT), there is no way to take XSLT output directly to XPathDocument. XslCompiledTransform doesn't provide XmlReader over its output. It can do XmWriter, but XPathDocument cannot be loaded via XmlWriter (this is likely to be fixed in post Orcas .NET version). The problem was solved though. Sergey Dubinets from the Microsoft XML Team contributed his excellent XslReader implementation, which provides an efficient way to read XSLT results as XmlReader. I later wrapped it all into MvpXslTransform class, which extends capabilities of the XslCompiledTransform class by adding support for transforming into XmlReader , vast collection of EXSLT extension functions, multiple outputs and transforming of IXPathNavigable along with XmlResolver. Here is finally code sample that says it all: using System; using System.Xml.Xsl; using System.Xml.XPath; using System.Xml; using Mvp.Xml.Common.Xsl; class Program { public static void Main() { MvpXslTransform xslt1 = new MvpXslTransform(); xslt1.Load("../../XSLTFile1.xslt"); MvpXslTransform xslt2 = new MvpXslTransform(); xslt2.Load("../../XSLTFile2.xslt"); XPathDocument doc = new XPathDocument("../../source.xml"); XmlReader stage1Output = xslt1.Transform(new XmlInput(doc), null); xslt2.Transform(new XmlInput(stage1Output), null, new XmlOutput(Console.Out)); } } Simple, fast and memory effective. Get Mvp.Xml library here. So here is nXSLTC.exe v1.0b - an experimental XSLT compiler for .NET 3.5 (Visual Studio "Orcas"). Get it here (free open-source). I probably shouldn't be building this tool, but I have my reasons. Why not? As a matter of fact, Mike Champion has announced back in February that Microsoft will provide XSLTC.exe tool in the next Visual Studio "Orcas", but apparently it didn't make it into March CTP, at least I didn't manage to find it. It probably will be included into the next drop. Why yes? First - this is the best way of learning new technology and then - I plan to build something bigger, which Microsoft won't be doing - XSLT project for Visual Studio, so I need this code anyway. Ok, so nXSLT.exe. It's a command line XSLT compiler for .NET 3.5. It compiles one or more XSLT stylesheets into DLL. These compiled stylesheets can be later used to transform XML documents using XslCompiledTransform class.
Continue reading nXSLTC - an experimental XSLT compiler for .NET 3.5.
Here is a problem: XSLT 1.0 sucks on generating XML character or entity references. I mean getting &foo; out of XSLT 1.0 is hard. The only ugly solution is disable-output-escaping hack, but it's a) optional, b)doesn't work in all scenarios (only when XSLT engine controls output serialization into bytes and c) works only on text nodes. Latter is real showstopper - you can't generate character or entity reference in attribute using XSLT 1.0. But now that we have XSLT 2.0, which is oh so better. What's XSLT 2.0 solution for the problem? I was writing about loading XSLT stylesheets embedded into assemblies (dll or exe) recently and Richard Quinn asked this very legitimate question:
Continue reading On embedding XSLT stylesheets into assemblies.
Now it's official, from the Microsoft XML Team:
Good. Very good news for those who invested in XSLT. XSLT 2.0 is sooooo much better,so much easier to develop with language. And I'm sure this new Microsoft XSLT 2.0 engine is gonna rock. This was meant to be one big huge milestone. If only it was done 3 years ago. I hope it's not too late though:
Wow. Congrats to everybody envolved. Lots of reading now. I just uploaded nxslt v2.1 release. In addition to the nxslt.exe command line tool it now also includes nxslt task implementation for NAnt and MSBuild.
Continue reading nxslt v2.1 released - now including NAnt/MSBuild task.
I was building NAnt and MSBuild tasks for the nxslt tool last two days and the bottom line of my experience is "previously I thought NAnt sucks, but now I know NAnt is brilliant and it's MSBuild who sucks really big way". My complaints about NAnt were that
Really minor ones as I realize now. Besides - NAnt is brilliant. While MSBuild appears to be more rigid and limited. Apparently it's impossible to create MSBuild task that uses something more than just attributes. I mean in NAnt I have this: <nxslt in="books.xml" style="books.xsl" out="out/params1.html"> <parameters> <parameter name="param2" namespaceuri="foo ns" value="param2 value"/> <parameter name="param1" namespaceuri="" value="param1 value"/> </parameters> </nxslt> MSBuild doesn't seem to be supporting such kind of tasks. MSBuild task only can have attributes, not children elements. It can have references to some global entities defined at the project level, such as properties and task items. At first I thought task items seem good candidates for holding XSLT parameters, because task items can have arbitrary metadata. And that's exactly how the Xslt task from the MSBuild Community Tasks Project passes XSLT parameters: <ItemGroup> <MyXslFile Include="foo.xsl"> <param>value</param> </MyXslFile> </ItemGroup> <Target Name="report" > <Xslt Inputs="@(XmlFiles)" Xsl="@(MyXslFile)" Output="$(testDir)\Report.html" /> </Target> Parameters here get attached to an XSLT file item definition, which seems to be reasonable until you realize that you might want to run the same stylesheet with different parameters? And what worse - above is actually plain wrong because it only provides "name=value" for a parameter, while in XSLT a parameter name is QName, i.e. XSLT parameter is a "{namespace URI}localname=value". And item metadata happens to be limited only to plain name=value. Metadata element can't have attributes or namespace prefix or be in a namespace... It's clear that MSBuild task item is a bad place to define XSLT parameters for my task. Last option I tried and on which I settled down is defining XSLT task parameters as global MSBuild project properties. Thanks God at least properties can have arbitrary XML substructure! Here is how it looks: <PropertyGroup> <XsltParameters> <Parameter Name="param1" Value="value111"/> <Parameter Name="param2" NamespaceUri="foo ns" Value="value222"/> </XsltParameters> </PropertyGroup> <Target Name="transform"> <Nxslt In="books.xml" Style="books.xsl" Out="Out/params1.html" Parameters="$(XsltParameters)"/> </Target> And here is how you implement it: create a string property "Parameters" in your task class. At the task execution time this property will receive <XsltParameters> element content (as a string!). Parse it with XmlReader and you are done. Beware - it's XML fragment, so parse it as such (ConformanceLevel.Fragment). Two problems with this approach - it makes me to define parameters globally, not locally (as in NAnt) - hence if I have several transformations in one project I should carefully watch out which parameters are for which transformation. Second - XML content as a string??? Otherwise it's good enough. Tomorrow I'm going to finish documenting the nxslt NAnt/MSBuild task and release it. Back in 2005 I was writing about speeding up Muenchian grouping in .NET 1.X. I was comparing three variants of the Muenchian grouping (using generate-id(), count() and set:distinct()). The conclusion was that XslTransform class in .NET 1.X really sucks when grouping using generate-id(), performs better with count() and the best with EXSLT set:distinct(). Here is that old graph: Today a reader reminded me I forgot to post similar results for .NET 2.0 and its new shiny XslCompiledTransform engine. So here it is. I was running simple XSLT stylesheet doing Muenchian grouping. Input documents contain 415, 830, 1660, 3320, 6640, 13280, 26560 and 53120 orders to be grouped. Besides being pretty damn faster that XslTransform, XslCompiledTransform shows expected results - there is no difference in a way you are doing Muenchian grouping in .NET 2.0 - all three variants I was testing are performing excellent with very very close results. Old XslTransform was full of bad surprises. Just switching to count() instead of generate-id() provided 7x performance boost in grouping. That was bad. Anybody digging into XslTransform sources knows how ridiculously badly generate-id() was implemented. Now XslCompiledTransform shows no surprises - works as expected. No tricks needed. That's a sign of a good quality software. Reporting errors in XSLT stylesheets is a task that almost nobody gets done right. Including me - error reporting in nxslt sucks in a big way. Probably that's because I'm just lazy bastard. But also lets face it - XslCompiledTransform API doesn't help here. Whenever there are XSLT loading (compilation) errors XslCompiledTransform.Load() method throws an XsltException containing description of the first error encountered by the compiler. But as a matter of fact internally XslCompiledTransform holds list of all errors and warnings (internal Errors property). It's just kept internal who knows why. Even Microsoft own products such as Visual Studio don't use this important information when reporting XSLT errors - Visual Studio's XML editor also displays only first error. That sucks. Anyway here is a piece of code written by Anton Lapounov, one of the guys behind XslCompiledTransform. It shows how to use internal Errors list via reflection (just remember you would need FullTrust for that) to report all XSLT compilation errors and warnings. The code is in the public domain - feel free to use it. I'm going to incorporate it into the next nxslt release. I'd modify it a little bit though - when for some reason (e.g. insufficient permissions) errors info isn't available you still have XsltException with at least first error info. private void Run(string[] args) { XslCompiledTransform xslt = new XslCompiledTransform(); try { xslt.Load(args[0]); } catch (XsltException) { string errors = GetCompileErrors(xslt); if (errors == null) { // Failed to obtain list of compile errors throw; } Console.Write(errors); } } // True to output full file names, false to output user-friendly file names private bool fullPaths = false; // Cached value of Environment.CurrentDirectory private string currentDir = null; /// Feel the difference - here is nxslt2 output: An error occurred while compiling stylesheet 'file:///D:/projects2005/Test22/Test22/test.xsl': System.Xml.Xsl.XslLoadException: Name cannot begin with the '1' character, hexadecimal value 0x31. And here is Anton's code output: test.xsl(11,5) : error : Name cannot begin with the '1' character, hexadecimal value 0x31. test.xsl(12,5) : error : Name cannot begin with the '0' character, hexadecimal value 0x30. test.xsl(13,5) : error : The empty string '' is not a valid name. test.xsl(14,5) : error : The ':' character, hexadecimal value 0x3A, cannot be included in a name. test.xsl(15,5) : error : Name cannot begin with the '-' character, hexadecimal value 0x2D. It's surprisingly easy in .NET 2.0. Obviously it can't be done with pure XSLT, but an extension function returning line number for a node takes literally two lines. The trick is to use XPathDocument, not XmlDocument to store source XML to be transformed. The key is IXmlLineInfo interface. Every XPathNavigator over XPathDocument implements this interface and provides line number and line position for every node in a document. Here is a small sample: using System; using System.Xml; using System.Xml.XPath; using System.Xml.Xsl; public class Test { static void Main() { XPathDocument xdoc = new XPathDocument("books.xml"); XslCompiledTransform xslt = new XslCompiledTransform(); xslt.Load("foo.xslt", XsltSettings.TrustedXslt, new XmlUrlResolver()); xslt.Transform(xdoc, null, Console.Out); } } <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ext="http://example.com/ext" extension-element-prefixes="ext"> <ms:script implements-prefix="ext" xmlns:ms="urn:schemas-microsoft-com:xslt" language="C#"> public int line(XPathNavigator node) { IXmlLineInfo lineInfo = node as IXmlLineInfo; return lineInfo != null ? lineInfo.LineNumber : 0; } </ms:script> <xsl:template match="/"> <foo> <xsl:value-of select="ext:line(//book)"> </foo> </xsl:template> </xsl:stylesheet> Ability to report line info is another reason to choose XPathDocument as a store for your XML (in read-only scenarios such as query or transformation) - in addition to better performance and smaller memory footprint. If you really need the same, but with XmlDocument, you have to extend DOM. I still own xsl.info and xpath.info domain names and still have no time to build anything around there. If anybody have any ideas about any community driven projects - let me know, I'm willing to donate domain name and may be participate. And if anybody want to buy these domain names - I'm willing to sell. Another coding horror story was reported in the microsoft.public.dotnet.xml newsgroup:
Cool. This is just a remainder for those who use XSLT scripting (msxsl:script) in .NET: watch out, this feature can be pure evil if used unwisely - it leaks memory and there is nothing you can do about it. The problem is that when XSLT stylesheet is loaded in .NET, msxsl:script is compiled into an assembly via CodeDOM and then loaded into memory, into the current application domain. Each time the stylesheet is loaded above process is repeated - new assembly is being generated and loaded into the application domain. But it's impossible to unload an assembly from application domain in .NET! Here is KB article on the topic. It says it applies to .NET 1.0 only, but don't be confused - the problem exists in .NET 1.1 and 2.0. Moreover I'm pretty much pessimistic about if it's gonna be fixed in the future. The solution is simple - just don't use script in XSLT unless you really really really have to. Especially on the server side - XSLT script and ASP.NET should never meet unless you take full resonsibility for caching compiled XslCompiledTransform. Use XSLT extension objects instead. Update. Of couse Yuriy reminds me that msxsl:script runs faster than an extension object, because msxsl:script is available at compile time and so XSLT compiler can generate direct calls, while extension objects are only available at run-time and so can only be called via reflection. That makes msxsl:script a preferrable but danger solution when your stylsheet makes lots of calls to extension functions. In a perfect world of course msxsl:script would be compiled into dynamic methods (just like XSLT itself), which are GC reclaimable, but I don't think CodeDOM is capable of doing this currently. I wonder if it's possible to compile C#/VB/J# method source into dynamic method anyway? Also it's interesting how to improve extension objects performance - what if extension objects could be passed at compile time? They are usually available anyway at that time too. Or what if compiled stylesheet could be "JITted" to direct calls instead of reflection? Sergey, Anton, can you please comment on this? Dimitre Novatchev has uploaded another FXSL 2.0 release. FXSL is the best ever XSLT library:
Now XPath 2.0 functions, operators and constructors as well as XSLT 2.0 functions have "higher-order FXSL wrappers that makes possible to use them as higher order functions and to create partial applications from them". To fully understand the value of this stuff take a look at Dimitre's article "Higher-Order Functional Programming with XSLT 2.0 and FXSL". Congratulations to all XSLT geeks - Dimitre Novatchev, XSLT extraordinaire is blogging! Whoha! Subscribed. Anton Lapounov is blogging! He's one of the brilliant guys responsible for XSLT in the Microsoft XML Team. If you are subscribed to my blog, you want to subscibe to "Anton Lapounov: XML XSLT and Beyond" blog too. How would you validate XSLT output on the fly without caching transformation result as a whole? That's easy - just use MvpXslTransform class that adds to the XslCompiledTransform class ability to transform into XmlReader and wrap that reader witth a validating reader. As a result - streaming validation, no memory hogging and ability to abort transformation at first validation error. Simple sample below.
XPathDocument doc = new XPathDocument("source.xml"); MvpXslTransform xslt = new MvpXslTransform(); xslt.Load("XSLTFile1.xslt"); XmlReader resultReader = xslt.Transform(new XmlInput(doc), null); XmlReaderSettings settings = new XmlReaderSettings(); settings.ValidationType = ValidationType.Schema; settings.Schemas.Add("", "orders.xsd"); XmlReader validatingReader = XmlReader.Create(resultReader, settings); XmlWriter w = XmlWriter.Create(Console.Out); w.WriteNode(validatingReader, false); w.Close(); You can get MvpXslTransform class with Mvp.Xml library v2.0 at the Mvp.Xml project site. W3C has released fresh versions of the Candidate Recommendations of XML Query 1.0, XSLT 2.0, XPath 2.0 and supporting documents. No big deal changes - xdt:* types has been moved to xs:* namespace (damn XML Schema). See new XQuery1/XPath2 type system below. Looks like XSLT2/XPath2/XQuery1 are moving fast toward Proposed Recommendation. What's weird is that new documents all say "This specification will remain a Candidate Recommendation until at least 28 February 2006." Must be a mistake. Anyway, what are now chances for XSLT 2.0 in the .NET? Next major .NET release (Orcas) is expected October 2007 or so (forget newly announced .NET 3.0, which is actually .NET 2.0 + Avalon + Indigo). Plenty of time for XSLT2 to reach Recommendation status, even provided that Microsoft actually freezes codebase 6 months before shipping.
Continue reading XSLT2/XPath2/XQuery1 fresh CRs.
I really enjoy seeing Michael Kay talking about working with XML in .NET. That makes me feel I might be not a freak after all.
Continue reading Saxon.NET and System.Xml.Xsl.
Martin Szugat, .NET and XML expert from Germany has published an article about using my eXml Web server control in ASP.NET 2.0. The article was published in the German dot.net magazin and now it also went online in the German MSDN: "Von der Quelle zum Kunden. Anzeige von XML-Daten auf dem Client in ASP.NET 2.0". Yep, German only, no English translation yet afaik. Well, cool anyway. XslCompiledTransform provides amazing transformation performance, but obviously not without a price. As with any compiling system the price is slower and quite resource consuming compilation stage. That's why it's very important to cache loaded XslCompiledTransform instance to avoid paying compilation price over again. One question that comes sometimes while implementing caching/pooling systems for XslCompiledTransform is how to check if XslCompiledTransform instance has been already loaded with a stylesheet? XslCompiledTransform design separates object construction and initialization for the sake of reusability (to be able to load another XSLT stylesheet into the same XslCompiledTransform instance). I believe that's a legacy issue as it contradicts with always-cache-loaded-XslCompiledTransform mantra. And unfortunately currently XslCompiledTransform provides no property to check if the stylesheet was already loaded and XslCompiledTransform instance is ready to be used. Hopefully in the next version we will get such one. But currently here is a trick that can be used - check OutputSettings property for not null. It's always null when Load() method has not been called and always not null after that. This is pretty much safe and I was assured by guys at the Microsoft XML team responsible for the XslCompiledTransform that this behaviour won't be changed. Well, "XSLT 2.0 in .NET" survey at the XML Lab site has ended back in January and I forgot to select a winner. Ooops. Let's finish this now. I obviously made a mistake requiring user registration for voting, but then I needed some way to identify a winner... Anyway, 40 people registered and voted (thanks guys), which is not bad for such a small unknown site. 72% need XSLT 2.0, 25% think it would be nice to have, 2% happy with XSLT 1.0. Quite predictable given my audience. And the winner (choosen truly randomly using EXSLT random:random-sequence() function) is Yoeri Van de Moortel from Belgium. Congratulations, Yoeri! Get in touch with me, I need your address to send the "XSLT 2.0 Programmer's Reference" book by Mike Kay (or some other XSLT book if you happens to own this one already). Ok, I'm back. I have updated eXml Web Server Control, which uses XslCompiledTransform, supports 70+ EXSLT functions, XInclude, friendly XML rendering, <?xml-stylesheet?>, embedded stylesheets etc. Martin Szugat found some bugs and kindly provided patches, thanks Martin! Additionally I implemented one small but useful feature users kept asking for - cache dependencies for imported/included stylesheets. That's when you have included or imported stylesheet and modify it - now eXml control notices it and recompiles XSLT on the next request. Go get eXml Web server control v1.1. Now I think about eXmlDataSource control... Free asp:XmlDataSource analog running XslCompiledTransform, supporting EXSLT, XInclude, <?xml-stylesheet?> and embedded stylesheets - it sounds useful, isn't it?
"XSLT 2.0 in .NET" survey at the XML Lab site ends in a week. Now that XslCompiledTransform in .NET 2.0 supports exsl:object-type() extension function I think a little intro is needed as this is really new function for Microsoft-oriented XSLT developers.
Continue reading exsl:object-type() XSLT extension function in .NET 2.0.
Sometimes it's useful to detect which XSLT engine your XSLT stylersheet is being executed by, e.g. to shortcut processing using an engine-specific extension function or to workaround a bug in particlular engine. Now that Microsoft alone ships 3 different XSLT engines - MSXML3/MSXML4/MSXML5/MSXML6, XslTransform and XslCompiledTransform, detecting XSLT engine from within XSLT stylesheet may be vital requirement. Here is how it can be done.
Continue reading Detecting version of Microsoft XSLT engine from within XSLT.
There are two new killer but undocumented features in Microsoft .NET 2.0 pertaining to EXSLT. Anybody like me regularly digging in System.Xml assembly probably knows it, but general audience is still unaware. So I want to share these secrets.
Continue reading Microsoft and EXSLT - secret breakthrough.
You say you know XSLT well? Try answer this quiz of XSLT 1.0 oddities by James Fuller.
Continue reading Quiz of XSLT 1.0 oddities by James Fuller.
Almost 2 years ago I published a post "Transforming WordML to HTML: Support for Images" showing how to hack Microsoft WordML2HTML stylesheet to support images. People kept telling me it doesn't support some weird image formats or header images. Moreover I realized it has a bug and didn't work with .NET 2.0. So finally I updated that damn stylesheet. Now I took another Microsoft WordML2HTML stylesheet as a base - that one that comes with Word 2003 XML Viewer tool. I think it's a better one. Anyway, I added to it a couple of templates so images now get decoded and saved externally and headers and footers are processed too (only header/footer for odd pages per section to be precise). Note: this stylesheet uses embedded C# script to decode images and so only works with .NET XSLT processors, such as XslTransform (.NET 1.1) or XslCompiledTransform (.NET 2.0). You can also run it with nxslt/nxslt2 command line tool. Here is a small demo.
Continue reading WordML2HTML with support for images stylesheet updated.
Slowly, gradually and with not much loud buzz both modern managed platforms - Java and .NET have switched to compiling XSLT implementations by default. First Java 5.0 made compiling Apache XSLTC processor a default transformer in JAXP 1.3 (instead of interpreting Apache XALAN). Then Microsoft released .NET 2.0 with new XSLT implementation - XslCompiledTransform replacing now obsolete XslTransform (guess what - interpreting one). XSLTC compiles XSLT into Java bytecode just like Java compiler, while XslCompiledTransform compiles XSLT into Microsoft Intermediate Language (MSIL) just like C# or VB compiler. The similarity is striking. Does it mean the era of interpreting XSLT processors is over and XSLT compilation is the future?
Continue reading The Raise of XSLT Compilation.
In the latest article "Schema-Aware Queries and Stylesheets" Michael Kay explaines how useful XML Schema-awareness is for XQuery queries and XSLT stylesheets. Miloslav Nic has announced the first snapshot of XSLT 2.0 tutorial at Zvon. Good stuff. I remember 5 year ago I was learning XSLT 1.0 using Zvon's tutorial... Dare thinks I'm making fruitless noise asking people if they need XSLT 2.0: I'm not sure how an informal survey in a blog would convince Microsoft one way or the other about implementing a technology. A business case to convince a product team to do something usually involves showing them that they will lose or gain significant marketshare or revenue by making a technology choice. A handful of XML geeks who want to see the latest and greatest XML specs implemented by Microsoft does not a business case make.Well Dare you underestimate the power of geeks and blogs :) Of course I'm not making a busines case. I'm looking for real world XSLT2 business cases (and not without results btw) trying to help Microsoft XML Team. I can't disclose more, but believe me guys we really can help now with such obvious Then he comes with some good advice: My advice to Oleg, if you want to see XSLT 2.0 in the .NET Framework then gather some like minded souls and build it yourself. Efforts like the MVP.XML library for the .NET Framework shows that there are a bunch of talented developers building cool enhancements to the basic XML story Microsoft provides in the .NET Framework.First of all as one of developers who runs Mvp.Xml project I should say that "a bunch" is a big overstatement here. Unfortunately only a really handful people are willing/have a chance to contribute to the project. Actually now, 3 years after I switched to .NET I'm pretty much pessimistic about open-source .NET projects altogether. There is something with people's attitude, it's different from that one in Java or linux world. And so I'm also kinda pessimistic about community developed .NET XSLT2 as I know the field. But that's of course my backup plan in any case. Also I found interesting some comments made to Dare's post. Take a look. And my personal take is similar to the one expressed by Mike Champion: Microsoft will implement XSLT2 anyway. The question is only when. I run into this article "Harnessing the BackPack API" by Michael K. Campbell in the new and very cool "XML 4 Fun" column at MSDN. The article is otherwise brilliant and really fun, but XML processing code samples are not so good. It's actually a great collection of XML processing antipatterns. Let's see.
Continue reading Processing XML in .NET: Antipatterns.
Moving along business cases Microsoft seeks to implement XSLT 2.0 I'm trying to gather some opinion statistics amongs developers working with XML and XSLT. So I'm holding this survey at the XML Lab site: Would you like to have XSLT 2.0 implementation in the .NET Framework? The possible answers are:
When the survey ends (probably in a month or so) one lucky survey taker from whatever part of the world choosen randomly will get the book. Note: you have to be registered on the Xml Lab site to vote. Sorry, but I need some simple way to identify the winner. Registration is simple and public - no email verification or something like, just fill in your name, password and email, get registered and then vote. Take your chance to influence Microsoft's decision on XSLT 2.0 and win XSLT 2.0 book!
Microsoft's
Exchange 2007 hosting software package is the main tool of
Exchange email outsourcing as many companies choose to use, since
Microsoft Exchange requires you to manage or pay for a
Microsoft Exchange server and sometimes outsourcing is the cheaper choice.
I'm glad to announce first release of the eXml - extended ASP.NET Xml Web Server Control. eXml is a free open-source ASP.NET 2.0 Web server control extending and improving standard ASP.NET XML Web server control. eXml Web server control uses new .NET 2.0 XSLT processor - XslCompiledTransform class to perform XSL transformations thus providing in average 400% performance boost and improved standard compliance. Additionally eXml Web server control provides built-in support for 70+ EXSLT extension functions, XML Inclusions (XInclude) 1.0, friendly XML rendering, <?xml-stylesheet?> XML processng instruction, embedded stylesheets and conditional whitespace stripping. eXml Download | eXml Documentaion | eXml Forum Enjoy!
With the right web site
design from a knowledgeable
web designer you may notice a significant difference in your
web page design that could help usability and you
web site design could impress some users as well.
If you are using XSLT and you think that XSLT 2.0 would provide you some real benefits, please drop a line of comment with a short explanation pleeeease. I'm collecting some arguments for XSLT 2.0, some real world scenarios that are hard with XSLT 1.0, some business cases when XSLT 2.0 would provide an additional value. That's really important if we want to have more than a single XSLT 2.0 implementation... PS. Of course I've read Kurt's "The Business Case for XSLT 2.0 " already. Update: I failed to stress it enough that it's not me who needs such kind of arguments. We have sort of unique chance to persuade one of software giants (guess which one) to support XSLT 2.0 now.
When it comes to
business email many growing companies need to keep in mind that their business email
services are a huge part of the communication in the business, and the right business email
can help to run a tight ship.
nxslt v2.0 (aka nxslt2) is available for download. This is first nxslt release for .NET 2.0. nxslt is a free feature-rich command line utility that allows to perform XSL Transformations (XSLT) using .NET Framework 2.0 XSLT implementation - System.Xml.Xsl.XslCompiledTransform class. nxslt is compatible with Microsoft's MSXSL.EXE tool and additionally supports XInclude 1.0, 70+ EXSLT and EXSLT.NET extension functions, multioutput, embedded stylesheets, custom XmlResolvers and custom extension functions, pretty printing etc etc etc.
Continue reading nxslt v2.0 released.
So Dimitre Novatchev invited me and I joined the FXSL (Functional Programming Library for XSLT) project. The FXSL functional programming library for XSLT provides XSLT programmers with a powerful reusable set of functions and a way to implement higher-order functions and use functions as first class objects in XSLT.I do think functional programming matters, that's where we are going and that FXSL rocks. I'm not sure what will be my role in the project, but I hope to be helpful. But first I have to refresh my functional programming skills with wonderful "Haskell: The Craft of Functional Programming" book by Simon Thompson. That's a big milestone in a 6-years-going-so-far design-by-committee experiment: XSLT 2.0, XQuery 1.0 and XPath 2.0 are finally W3C Candidate Recommendations. That means that W3C now officially calls for implementations (which shows another weirdness of the design-by-committee process as XQuery alone has about 40 implementations already as per Ken North). CR phase will last at least till 28 February 2006, that means late 2006 is probably the timeframe for the XSLT 2.0, XQuery 1.0 and XPath 2.0 Recommendations. There is a known problem with new XSLT processor in just released Microsoft .NET 2.0 - XslCompiledTransform class doesn't support pull mode XSLT - outputting XSLT result in XmlReader form as obsolete XslTransform class did. I'm happy to announce that the problem is solved now. Sergey Dubinets from the Microsoft XML Team has developed XslReader implementation which allows to read XSLT output via XmlReader in a very efficient way - i.e. without full output buffering. It's concurrent writer-reader bridge, which runs XSLT in another thread and lets it to produce another output portion whenever reader wants to read more. And Sergey kindly donated his code to the Mvp.Xml project, so it will be part of the Common module of Mvp.Xml library v2.0, which is going to be released really really really really soon. Kudos to Sergey! Stay tuned. Another minor nxslt release is available - v1.6.4. This version adds support for the "extension-element-prefixes" attribute and fixes a glitch in transformation timings reporting. What's the problem with "extension-element-prefixes" attribute? When using <exsl:document> extension element to produce multiple outputs some EXSLT-aware XSLT tools (like 4XSLT) rightly require "exsl" prefix to be registered in the "extension-element-prefixes" attribute. The problem was that .NET's XslTransform class while not supporting extension elements at all, throws an exception once encountering "extension-element-prefixes" attribute. So for running the same stylesheet with nxslt one had to remove "extension-element-prefixes" attribute, and with other tools - add it. Bad bad bad. So in nxslt 1.6.4 I fixed the issue by hiding "extension-element-prefixes" attribute from XslTransform class, so now you can use it in you stylesheets and enjoy better portability. As a matter of interest, new .NET 2.0 XSLT processor - XslCompiledTransform class, while still not supporting extension elements, at least ignores "extension-element-prefixes" attribute. Good. Opera 9.0 Preview 1 released October 20 finally adds support for XSLT and XPath to the Opera browser. Finally they are awake. Good move, but it might be too late for the Opera. [Via <XSLT:Blog/>] nxslt 1.6.1 is available for download at the xmllab.net. This is bug fix only release. Marc Stober reported that when running into XInclude error he got MissingManifestResourceException. Apparently XInclude string resources weren't compiled into the nxslt.exe. This release fixes this bug. Thanks for reporting, Marc! nxslt is free feature-rich command line .NET XSLT utility, supporting EXSLT.NET, XInclude, multiple output etc etc etc. No new features in this release. Instead I'm working on nxslt2 - nxslt for .NET 2.0. Jeni Tennison has announced an utility for unit-testing XSLT stylesheets: I've just developed a set of stylesheets that are designed to support unit testing of XSLT stylesheets. You embed tests in the stylesheet and can run a script (or configure your editing environment) to extract and run them and create an HTML report on the result. Further details and the download is available from:XSLT 2.0 engine (Saxon 8.4B or later) is required. Also she announced that her long-awaited "Beginning XSLT 2.0: From Novice to Professional" book is finally out: Michael Kay has released Saxon XSLT and XQuery processor v8.5. This new release implements some very interesting optimizations (available only in commercial version though) and new abilities, one of which is probably worth to implement in EXSLT.NET module.
Continue reading Saxon 8.5, new optimizations and abilities.
Colin Paul Adams has announced Gobo Eiffel XSLT - free XSLT 2.0 processor written in Eiffel. Gexslt is intended to conform to a Basic-level XSLT 2.0 Processor and currently is still under development. Win32 compiled version can be downloaded at http://www.gobosoft.com/download/gobo34.zip. nxslt 1.6 and nxslt2 Beta1 are available for download. For those not familiar with nxslt: nxslt is free feature-rich .NET XSLT Command Line Utility. nxslt 1.6 is the next version for the .NET 1.X Frameworks. New features include optionality for source XML or stylesheet, pretty printing, ASCII only escaped output and support for "omit-xml-declaration" attribute of the exsl:document extension element. nxslt2 Beta1 is the first beta version of the next major nxslt release. nxslt2 uses new XSLT 1.0 processor in the .NET 2.0 Framework - System.Xml.Xsl.XslCompiledTransform class. Hence it requires .NET 2.0 Beta2 (which you can download here) or higher. As a first beta version, nxslt2 Beta1 is quite limited - no support for XInclude, EXSLT, multiple output and embedded stylesheets. As far as I port EXSLT.NET and XInclude.NET to .NET 2.0 I'll update nxslt2. New Microsoft XSLT Processor (XslCompiledTransform) is a great stuff. Compiles XSLT to MSIL and runs as fast as MSXML4. I'll be writing about it a lot soon. With nxslt2 you can give it a whirl. I know I'm late, but anyway here is the latest Dimitre's puzzle. Don't post your anwers here, just send them him to dnovatchev AT gmail DOT com. Dimitre will be collecting answers only for another week, so hurry up. I just started reading the book "The Da Vinci code" and this resulted in having some fun with XSLT 2.0, Saxon 8.4 and Saxon.NET. Just look here. AJAXSLT is an implementation of XSL-T in JavaScript, intended for use in fat web pages, which are nowadays referred to as AJAX applications. Because XSL-T uses XPath, it is also an implementation of XPath that can be used independently of XSL-T.That's weird. Wait, all modern browsers (ok, except Opera) support XSLT natvely, don't they? Well, here is how they explain the goals: Both XPath and XSL-T are built into some of the modern browsers, however not in all. This library runs on many browsers, including those that don't support XSLT adaequately or at all, which is why the library was written in the first place. (See BROWSER COMPATIBILITY, below.)And more: Safari/2.0 has XSL-T built in, but it is not exposed to JavaScript, but is only applied to XML documents that have a stylesheet declaration when they are loaded.Hmmmm, still weird. But still cool. Any efforts to bring XSLT client side are always cool. I'm glad to see Google supporting the idea. It's official now - we (XML MVPs) agreed and Dare (as EXSLT.NET project owner) has approved an integration of the EXSLT.NET project into the Mvp.Xml library. All EXSLT.NET project contributors may ask to be added as developers to the Mvp.Xml project. I will be moving code soon, as well as doing some EXSLT.NET development. Current plans are: .NET 2.0 version and support for XSLT 2.0 stylesheet functions. Stay tuned. Microsoft's XML Team is asking you: XSLT 2.0 -Don't miss a chance to speak up. Go post a comment. Some users report that after installing Netscape 8 Internet Explorer and other IE-based browsers usch as Avant browser stop applying XSLT stylesheets, even the default stylesheet used to render XML documents. That probably has something to do with "Firefox or IE6 rendering" feature in Netscape. Beware.
If you do make your own web site design
make sure you research various web site design
firms before you invest money into a web
designer who might know less about web page design
than you do.
As many were saying, XSLT is finally coming to client side. The rumors came true today - latest version of the Safari browser from Apple supports XSLT via libxslt. Now what about Opera? [Via Cafe con Leche] As usually very long post (an article actually) by Kurt Cagle on "The Business Case for XSLT 2.0". Explains why XSLT 2.0 is good and why Microsoft should implement it. With Michael Champion's comments, worth reading. This is amazing. Adam Kinney (Xamlon guy) runs his new Adam Kinney.com has been redesigned, restructured and refactored. The new site has been inspired by my hate fo comment spam, interest in XSLT 2.0, desire to lose SQL and move to XML, wanting to build more than just a blog (i.e. articles, art galleries, events) and my continually desire to build all my own tools over and over again.As a matter of interest his site is rendered as both HTML and XAML - that reminds me that XSLT was actually designed exactly for such stuff. [Via <XSLT:Blog/>] Here is a really nice wrap up by Mike Kay on what benefits XSLT gets from using XML syntax: I think the benefits are:And there is a misconception about XQueryX (XML syntax for XQuery). XQueryX isn't an alternative way to write XQuery queries using XML syntax (that way is called XSLT). It's more like formalized standard XML based AST format for XQuery processors. It's designed to be unconvenient to read and write by humans. It's just ridiculously wordy and low-level. m.david starts his new project on Monday - sort of community XSLT learning using wonderful "Beginning XSLT" book by Jeni Tennison Anyone and everyone is welcome to join in this effort to become better XSLT programmers. While I intend to do all I can to keep things moving forward throughout the course of this "adventure" there is no set schedule. I plan to submit two to three posts a day to act as food and fodder but by no means will these be the required focus. By utilizing the blog format it allows those who are not ready to move on the ability to stay where they're at, asking questions via comments and relying on answers from the community to help in better understanding that particular area of XSLT. This format also allows those who are ready to move ahead the ability to do so without feeling the need to wait for others to catch up. In many ways this will allow a relaxed, self-paced environment for you to jump in at any point and begin to better your XSLT programming skills. This also allows for those only interested to better their skills in certain aspects of the language the ability to jump in and out as they please. In the end we will hopefully have created a nice reference for others to come along and utilize as well as ourselves to reference as needs be.I wish I learn XSLT this way! I was climbing hard - reading XSLT/XPath specs first and then struggling with crappy Lotus XSL engine and only then I saw the light - Mike Kay's XSLT Bible. If you want to learn XSLT easy - join UnderstandingXSLT.com's "adventure", it's also free anyway. I'll be there and I'm sure Dimitre Novatchev will be there, right Dimitre? It's worth to mention also that SyncRO Soft Ltd, the maker of the <oXygen/> XML Editor offers 15% discount on their products for UnderstandingXSLT community members. More details here. As another non-obvious outcome of the recent browser war wave and the raise of Firefox browser is growing appreciation of XSLT as a useful client-side Web technology. That "An Introduction to Client-Side XSLT: It's Not Just for Server Geeks Anymore" article at digital-web.com is making me believe XSLT is finally coming to the client-side. Another good news is that Mac's Safari browser is going to support XSLT via libxslt in the next release. Kudos! Wow, I've heard about some hardware XML routers, but today I saw an ad banner about hardware XSLT accelerator. Holy cow! Here is some marketing blah-bkah-blah:
Standards based XSLT processing is computationally intensive - it overburdens the server infrastructure resulting in poor user experience, high server infrastructure costs and scalability limitations. By delivering order of magnitude or better acceleration for XSLT processing - the XML Speedway significantly reduces the infrastructure costs, improves scalability and availability of the total solution. The XML Speedway provides this world-class performance through Sarvega's acclaimed highly optimized XESOS™ technology. Further, through XML Compression, end-to-end response time is improved regardless of location or network connection.And here is some meat: XML Speedway can be deployed in a reverse-proxy in-line and server-assist modes with JaxP and C++ API. Flexibility extends to the variety of means available to de-reference XSL stylesheets, enable pipelined transformations, provides built-in support for various XSLT engines, XSLT and XML Schema caching and the ability to concurrently offload disparate backend applications with their own sets of transformations.And what this box can do: Wire Speed XSLT Processing: Not bad. They say FOXSports.com is already using it. I wonder where is the price list. PS. Hey, that's Sarvega company - once they wanted to hire me, now I see why :) M. David Peterson, coordinator of the x2x2x.org community open-source project (known by the Saxon.NET, AspectXML, and xameleon projects) started a blog at xsltblog.com. The blog's description is "An ongoing weblog of current topics from the XSLT development community & other XML/XSLT related news items. Hosted, maintained, & edited by M. David Peterson.". Subscribed. I missed that point somehow: The trouble is that XSLT allows regions of a stylesheet to belong to different versions. In XSLT 1.0, you can put an xsl:version attribute on any literal result element to indicate the version of XSLT used in the content of that element. In XSLT 2.0, any XSLT element can have a version attribute, and any other element can have a xsl:version attribute that does the same thing.It can be quite useful when upgrading stylesheets step by step, but I don't think such mix is useful otherwise provided huge difference in XPath 1.0 and XPath 2.0 data models and XSLT 1.0 and XSLT 2.0 behaviours (even in backwards compatible mode). And it's a disaster for anyone impementing XSLT 2.0 from scratch. Now I wonder how are we going to implement this feature in the XQP project? Steve Ball announced XSLT Standard Library version 1.2.1 - an open source, pure XSLT (extensions free) collection of commonly-used templates. New stuff includes new SVG and comparison modules and new functions in string, date-time and math modules. Interesting post by Michael Kay on detecting cycles in graphs using XSLT and XQuery: > I have XML data in the form of a graph (nodes, edges) and ITake a look at the stylesheet here. And now even more intriguing: The book also shows how to generalize this so the code that looks for cycles is independent of the way that the nodes and arcs are implemented. Unfortunately this generalization relies on Dimitre Novatchev's technique for simulating higher-order functions, which is dependent on XSLT and won't work in XQuery.Wow, I can't wait for the book to arrive. That's going to be my next one in reading queue, out of all priorities. Things turn slowly nowadays. Michael Kay on XSLT 2.0 perspectives: We're going to have to have a second Last Call because of the number of comments received. You can't do a Last Call in much less than four months. The CR phase these days for a complex spec is rarely less than 12 months, because of the requirement to create a test suite and demonstrate interoperable implementations. So I personally think that reaching full Rec status in 2005 is looking unlikely. That's a personal view, not an official W3C one. Perhaps some tricky implementation of XSLT could figure out if a stylesheet is streamable and switch to a streaming strategy.That would be rather effective optimization indeed. But how that could be implemented in XSLT/XQuery processor? Obviously full-blown stylesheet analysis would be feasible only having schema information available (that means XSLT 2.0/XQuery 1.0), but even without it it's still easy to detect some common streaming-friendly cases, such as: 1. Renaming elements or changing namespaces, e.g.: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="foo"> <bar> <xsl:apply-templates select="@*|node()"/> </bar> </xsl:template> </xsl:stylesheet>It's easy to see that the stylesheet has identity transformation and a template for "foo" element, which actually replaces "foo" witrh "bar". Above is detectable and could be done more effective with XmlReader or XmlReader/XmlWriter pipeline. 2. Translating attributes to elements or similar, e.g. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <xsl:template match="foo"> <xsl:copy> <xsl:for-each select="@*"> <xsl:element name="{name()}"> <xsl:value-of select="."/> </xsl:element> </xsl:for-each> <xsl:apply-templates select="node()"/> </xsl:copy> </xsl:template> </xsl:stylesheet>Also that's detectable what above stylesheet is doing and is implemenatable with only XmlReader or XmlReader/XmlWriter internally instead. 3. Pretty-printing using XSLT - frequent case, easily detectable - an ideal candidate for optimization. Just stream input through XmlTextWriter internally. 4. Adding root element or adding header/footer - ditto. 5. Changing PIs in the prolog (<?xml-stylesheet>). 6. What else? Obviously to gain something with all above implemented XSLT processor should be given plain Stream/TextReader/XmlReader as input, not any already-in-memory XML store. Here is interesting paper "XSLT and XPath Optimization" by Michael Kay. That's materials of Michael's talk at recent XML Europe conference. In this paper Michael reveals details of the XSLT and XPath optimizations performed internally by SAXON (XSLT and XQuery processor): This paper describes the main techniques used by the Saxon XSLT and XQuery processor (http://saxon.sf.net/) to optimize the execution of XSLT stylesheets and XPath expressions, and reviews some additional XSLT and XPath optimization techniques that are not (yet) used in Saxon.A must reading for those developing or thinking to develop XPath/XQuery/XSLT plumbing. [Via XML.com]
Continue reading XSLT and XPath Optimization.
That's a milestone in XSLT technology life - the most famous Java XSLT processor Saxon goes commercial. Here is what Michael Kay (author of Saxon and XSLT 2.0 editor) writes: In March 2004 I founded Saxonica Limited to provide ongoing development and support of Saxon as a commercial venture. My intent is to continue to produce the basic (non-schema-aware) version of Saxon as an open source product, while at the same time delivering professional services and additional modules (including a schema-aware processor) as commercial offerings.Well, that was predicted. The complexity schema added to XSLT closes the era of one-man XSLT processors. Another interesting quote from Mike - about Saxon processor (it's not "XSLT processor" anymore, but "collection of tools" as it supports XPath 1.0, XSLT 1.0, XPath 2.0, XSLT 2.0 and XQuery 1.0) name: The name Saxon was chosen because originally it was a layer on top of SAX. Also, it originally used the Aelfred parser (among others); Aelfred of course was a Saxon king... I've released nxslt.exe utility version 1.4. It's maintenance release. Changes are:
.NET XSLT command line utility, version 1.4 (Running under .NET 1.1) The rule is simple - nxslt.exe requires .NET Framework it's compiled for. By default nxslt.exe is compled for .NET 1.1 and thus can't run under .NET 1.0. Instead use nxslt-.NET1.0.exe version (feel free to rename it too). For testing .NET 1.2 use nxslt-.NET1.2.exe version. No need to say, I appreciate any comments|critics|suggestions|donations|not(spam). Not too much, right. For the next nxslt.exe release (March probably) I'm going to implement basic XSLT profiling, tracing and may be rudimentary debugging functionality. Stay tuned. Everybody knows grouping in XSLT is kinda advanced topic. Muenchian method is just a nightmare for XSLT newbies and XSLT-related newsgroups are full of help-me-to-group-in-xsl postings. Well, and I and fellows do answer such questions day afer day. Should admit that's a way booooring. Now I wonder why we don't use EXSLT to simplify grouping technique so even newsbies can grasp it quickly? I'm talking about set:distinct function, which can replace the dreadful and mysterious generate-id()=generate-id(key('theKey', foo)[1]) step in Muenchian method. Here is a common grouping sample along with both classical solution (pure Muenchian method) and improved one (EXSLT-based). So compare and say which is more understandable. Source XML, list of cities. <doc> <city name="Paris" country="France"/> <city name="Madrid" country="Spain"/> <city name="Vienna" country="Austria"/> <city name="Barcelona" country="Spain"/> <city name="Salzburg" country="Austria"/> <city name="Bonn" country="Germany"/> <city name="Lyon" country="France"/> <city name="Hannover" country="Germany"/> <city name="Calais" country="France"/> <city name="Berlin" country="Germany"/> </doc>The task is to group them by countries: <doc> <country name="France"> <city>Paris</city> <city>Lyon</city> <city>Calais</city> </country> <country name="Spain"> <city>Madrid</city> <city>Barcelona</city> </country> <country name="Austria"> <city>Vienna</city> <city>Salzburg</city> </country> <country name="Germany"> <city>Bonn</city> <city>Hannover</city> <city>Berlin</city> </country> </doc> Solution #1, classical Muenchian method: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:key name="kCountry" match="city" use="@country"/> <xsl:template match="doc"> <doc> <xsl:for-each select="city[generate-id()=generate-id(key('kCountry', @country)[1])]"> <country name="{@country}"> <xsl:apply-templates select="key('kCountry', @country)"/> </country> </xsl:for-each> </doc> </xsl:template> <xsl:template match="city"> <city><xsl:value-of select="@name"/></city> </xsl:template> </xsl:stylesheet> Solution #2, EXSLT based one: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:set="http://exslt.org/sets" exclude-result-prefixes="set"> <xsl:key name="kCountry" match="city" use="@country"/> <xsl:template match="doc"> <doc> <xsl:for-each select="set:distinct(city/@country)"> <country name="{.}"> <xsl:apply-templates select="key('kCountry', .)"/> </country> </xsl:for-each> </doc> </xsl:template> <xsl:template match="city"> <city><xsl:value-of select="@name"/></city> </xsl:template> </xsl:stylesheet> Both stylesheets are almost the same except bolded parts. My measurements (using nxslt.exe with -t option) say it takes the same time to execute both stylesheets and frankly I don't see why it could be different. But set:distinct(city/@country) and city[generate-id()=generate-id(key('kCountry', @country)[1])] do differ, don't they? Interesting article about incremental XSLT. I only wish it comes true some day.
I've got an invitation from Mono guys to consider contributing to Mono Managed XSLT Processor implemenation (now they have only a wrapper around libxslt engine). Well, we at Multiconn have designed and built one XSLT processor couple of years ago (it's quite specialized and highly (may be even too) optimized XSLT 1.0 engine for mainframe OLTP environment, written in ANSI C). It was great opportunity to learn XPath and XSLT thoroughly from cover to cover and it was actually cool (apart from programming in ANSI C nowadays). I definitely have some ideas about XSLT implementation, especially if you have C#, .NET plumbing available and considering rumors around next Microsoft .NET XSLT impl :). So it's really awfully tempting.
But it's quite big open source project and I'm too busy unfortunately... I have long TODO list of not-less-interesing (but smaller) projects, I've started another article, I'm in MCAD cert preparation curve after all. And day work of course - we've just finished one trivial Web Service project, but another BizTalk-related one is on the horizon already. So I'm not sure... Dare has published a new cool article at his MSDN Extreme XML column: "EXSLT: Enhancing the Power of XSLT". It's about Dare's implementation of 60+ EXSLT functions for .NET XSLT processor. Kudos! That was a pile of work due to number of functions, I'm sure the community will appreciate Dare's efforts to let users just write set:distinct(//foo) instead of using advanced Muenchian grouping method involving keys and fiddling with generated IDs just to get set of distinct nodes. One serious question is about function names: due to technical issues it's impossible in .NET to create XSLT extension function with hyphenated name, like add-duration(). That's because in .NET XSLT extension function names are reflected directly to extension object methods and afaik (I wish I'm wrong) there is no way to fake method's name other that hacking IL code in a compiled assembly. It really hurts portability, which is on the one hand what EXSLT initiative is about and I'm sure some people will say it's one more embrace-and-extend example of Microsoft politics. Come on, I'm not MSFT worker and believe me that's not the case, really. That's completely technical issue, I also desperately tried to find any clean workaround but with no success. Look at it from another point of view - XSLT programmers do really need these functions, and that's fine to give them EXSLT even if some functions have nonportable names. Fortunately we've found a solution for another even more serious problem. I believe Dare's implementation should outgrow article's boundaries and become a project on its own, e.g. at GotDotNet Workspaces, there is much room for enhancements and I'm sure more versions to come. I'm going to provide EXSLT support to my nxslt pygmy - .NET XSLT command line utility, that should be handy to encapsulate (hacked to provide EXSLT-conformant function names?) Dare's implementation within nxslt and to get EXSLT-aware .NET XSLT processor. Tomorrow. New XSLT 2.0 Working Draft has been published. Interesting changes since November 2002 version:
Also 9 (yes, nine) other XPath/XQuery/XSLT related Working Drafts have been published, see http://www.w3.org/TR. Kirk Allen Evans has posted a recursive XSLT template to transform CSV into XML. Being low-level substring functions based it's obviously quite verbose and convolute, what was fairly enough pointed out by Dare. He has provided 10-lines C# version also. What I wanted to add to this subject is that such example perfectly illustrates how radically EXSLT extensions may improve XSLT 1.0 coding. (btw, Dare is working on the implementation of EXSLT functions for .NET and I believe it would be great addition to .NET XSLT programming practice). Look yourself: here is EXSLT version, which makes use of str:tokenize extension function (note, even smaller than Dare's C# one): <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://exslt.org/strings" exclude-result-prefixes="str"> <xsl:include href="d:/xsl/str.tokenize.msxsl.xsl"/> <xsl:template match="root"> <root> <xsl:for-each select="str:tokenize(.,'
')"> <row> <xsl:for-each select="str:tokenize(.,',')"> <elem><xsl:value-of select="."/></elem> </xsl:for-each> </row> </xsl:for-each> </root> </xsl:template> </xsl:stylesheet> So, XSLT perfectly able to handle this, it just needs tokenizing facility, like C# has and what for producing XML - IMO XSLT is the best hammer on the market. I agree though that for pure CSV2XML conversion XSLT may be not a right tool, if it was my project, I'd make use of SAX filter or something like Chris Lovett's XmlCsvReader. Oracle XDK v10 Beta Release supports XSLT 2.0, XPath 2.0 and XPath 2.0 Data Model (all working drafts dated 11th November 2002). It's not clear to which extent all that jazz is supported, but anyway, that's good news. And AFAIK Apache guys at Xalan team are working on Xalan 3.0, so more to come. I have released nxslt version 1.1. nxslt is .NET XSLT command line utility, written in C#. Timings are now more accurate, I'm using System.Diagnostics.PerformanceCounter class now. Two new features: custom URI resolver and multiple output. First one is trivial - it's now possible to provide a resolver class name to resolve URI's in xsl:include, xsl:import elements and document() function. So basically nxslt is ready for XML Catalogs, lets just wait till any .NET implementation appears. Actually I have considered to implement it, but decided XInclude.NET project looks more interesting to me at the moment. Multiple output - using partially supported exsl:document extension element it's now possible to create multiple result documents in one transformation run. Extremely powerful stuff, believe me. I would like not to unveil implementation details though (haha, it's open source) as I'm going to publish an article about it. So enjoy. nxslt can be used in command line or integrated into IDE, such as XML Spy or Xselerator. btw, wouldn't it be nice to intergate it with VS.NET? I imagine one-click XSLT transformation inside VS.NET XML editor for instance. |
Recent Comments