Hello Saxon on .NET! - An ASP.NET Introduction

by M. David Peterson

Related link: http://channelxml.com/saxon/dotnet/hellosaxonondotnet.zip



[QUICK-UPDATE: Forgot for some silly reason to add the link to the live working sample of this code.]



<%@ Page Trace="false" Language="C#" Debug="false"%>
<%@ Import Namespace="System" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="Saxon.Api" %>

<script runat="server">

// NOTE: Saxon now uses System.Xml internally on the .NET platform.
// We could import it and use any of its derived classes, methods, and so forth,
// but in this example we will be using a FileStream for both the source
// and transformation files, and Saxon will be taking care of things from there,
// so theres no need to import System.Xml for this particular example.
void Page_Load(Object sender, EventArgs e)
{
// Create two strings that represent the source file and
// transformations file. These values could be set using
// a variety of methods (e.g. QueryString) but for now
// we will keep things simple and hardcode these values.
String sourceUri = Server.MapPath("index.xml");
String xsltUri = Server.MapPath("index.xslt");

// The new Saxon engine for the .NET platform allows the
// ability to pass in a Stream instance directly.
// Given that the Stream class implements IDisposable, we
// can use the 'using' keyword/codeblock to ensure that
// our resources are properly cleaned up, freeing up
// valuable system resources in the process.
// [UPDATE: Check that. This really should read
// close all of the file streams we opened automagically.
// While its true we're cleaning up system resources
// It's not like theres really a choice. One way
// or another the stream needs to be closed, this
// Just does this for us so we don't have to worry about it.
using (FileStream sXml = File.OpenRead(sourceUri))
{
// We need to do this for each Stream that we pass in for processing.
using (FileStream sXsl = File.OpenRead(xsltUri))
{
// Now we simply create a Processor instance.
Processor processor = new Processor();

// Load the source document into a DocumentBuilder
DocumentBuilder builder = processor.NewDocumentBuilder();

// Because we have created the DocumentBuilder with a file stream
// we need to set the BaseUri manually, as this information is no
// longer available to the Saxon internals when a Stream, regardless
// of what the source of this Stream happens to be, is used for creating
// the DocumentBuilder instance. With this in mind, we need to create
// an instance of a Uri using the sourceUri we created above.
Uri sUri = new Uri(sourceUri);

// Now set the baseUri for the builder we created.
builder.BaseUri = sUri;

// Instantiating the Build method of the DocumentBuilder class will then
// provide the proper XdmNode type for processing.
XdmNode input = builder.Build(sXml);

// Create a transformer for the transformation file, compiling and loading this
// file using the NewXsltCompiler method of the Saxon.Api namespace.
XsltTransformer transformer = processor.NewXsltCompiler().Compile(sXsl).Load();

// Set the root node of the source document to be the initial context node.
transformer.InitialContextNode = input;

// Create a serializer
Serializer serializer = new Serializer();

// Set the serializer to write the transformation output directly
// to ASP.NET's Response.Output stream.
serializer.SetOutputWriter(Response.Output);

// Run the transformation.
transformer.Run(serializer);

// and we're done. :)
}
}
}
</script>



XML File:


<?xml version="1.0" encoding="utf-8" ?>
<message>
<Hello>Saxon on .NET!</Hello>
</message>



XSLT 2.0 File:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:output method="text"/>

<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>

<xsl:template match="message">
<xsl:apply-templates />
</xsl:template>

<xsl:template match="Hello">
Hello <xsl:value-of select="." />
</xsl:template>

</xsl:transform>



Result:



Hello Saxon on .NET!



Access zipped source code files. These files require the Saxon 8.7 processor binaries for the .NET platform, accessible directly from Saxonica.



If you are new to the .NET platform, and would like to begin playing with this source code, I highly recommend one of the Visual Studio 2005 Express Editions, currently available for free directly from the Visual Studio product page on Microsoft.com. On Linux, Mac, or other supported environment I would recommend paying the Mono-Project a visit :)



NOTE: All of the above source code (excluding the Saxon source code, which is licensed under the Mozilla Public 1.0 License) is licensed under whichever license fits your personal needs and desires best. :) Enjoy!








Please feel free to comment, ask questions, etc.. that are specific to this implementation. Technical support for the Saxon Processing Engine should, as always, be directed through the SourceForge support list accessible from http://saxon.sf.net