Click here to Skip to main content
15,867,308 members
Articles / Programming Languages / XML
Article

XSLT Unleashed

Rate me:
Please Sign up or sign in to vote.
4.81/5 (17 votes)
11 Jan 20072 min read 61.5K   534   54   15
Another use for XML and XSLT

Introduction

Following on from a previous article I posted, I thought I'd share another use for XML and XSLT, albeit an uncommon one.

The Problem

You have an application which imports data from an XML file. Odds are that the schema changes or a new namespace is introduced. You will need to rewrite your loader code and update the application at the client. Alternatively, you don't enjoy writing lots of loopy code using XPathNavigators and XPathNodeIterators, or worse the XMLDocument.

The Solution

Use XSLT to transform the source XML data into XSLT extension calls to a object which will persist the imported data to a backing store. This way, you can package the XML importers as external files to the application, and just deploy a new XSLT whenever the source changes. Since XSLT is designed to manipulate XML, it offers a more elegant approach to extracting the data than writing loopy code. Other nasties like supporting multiple namespaces are easy to do using XSLT. An interesting side effect is that the output of the transform can be used as an activity log of the imports activities.

How it Works

The attached sample application imports order data from an XML file to a backing store. The source XML data is transformed by an XSLT which invokes methods on an extension object to do the work of creating the order and details in the backing store.

XSLT invoking methods

An instance of the OrderEntry() class is created and added to the XslTransform as an extension under the urn:chrisstefano.xslt.orderentry namespace.

C#
// load orders document (assume in bin/Debug or bin/Release dir)
XmlDocument ordersDoc = new XmlDocument();
ordersDoc.Load("Orders.xml");

// load order processor XSLT
XslTransform orderProcessor = new XslTransform();
orderProcessor.Load("LoadOrder.xslt");

XsltArgumentList args = new XsltArgumentList();

// associate the extension object with a namespace, so
// it can be invoked within the transformation
args.AddExtensionObject("urn:chrisstefano.xslt.orderentry", 
                            new OrderEntry());

XmlTextWriter output = new XmlTextWriter("output.xml", 
                        System.Text.Encoding.UTF8); 

orderProcessor.Transform(ordersDoc.CreateNavigator(), args, output, null);

output.Close();

The OrderEntry class contains two methods for interfacing with the backing store.

Order Entry extension class

The int CreateOrder(string) method creates the order header record and returns an int which represents the order identifier. The decimal CreateOrderLine(int, string, int, decimal) method takes the order identifier and some other information and creates the order line. It returns a decimal value which represents the value of the order line. This value is included in the output of the transformation.

This extension namespace is declared in the XSLT with the prefix ext. Method calls on the extension are written using the prefix and the method name.

XML
<xsl:stylesheet version="1.0" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:ext="urn:chrisstefano.xslt.orderentry">

   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

  <xsl:template match="/">
    <OrderProcessing>
      <xsl:apply-templates select="Orders"/>    
    </OrderProcessing>
  </xsl:template>
  
  <xsl:template match="Orders">
    <xsl:apply-templates select="Order">
      <xsl:sort select="@date" />      
    </xsl:apply-templates>    
  </xsl:template>
  
  <xsl:template match="Order">
    
    <!-- invoke extension to create the order -->
    <!-- save the order id into a variable -->
    
    <xsl:variable name="order-id">
    <xsl:value-of select="ext:CreateOrder(@customer)"/></xsl:variable>
    
    <!-- write out processing step -->
    <OrderProcessed order-id="{$order-id}" customer="{@customer}">
    
      <xsl:apply-templates select="OrderLine">
        <xsl:with-param name="order-id" select="$order-id" />
      </xsl:apply-templates>
      
    </OrderProcessed>
    
  </xsl:template>
  
  <xsl:template match="OrderLine">
    <xsl:param name="order-id">0</xsl:param>
    
    <!-- invoke extension function to create order line -->
    <!-- save consideration into variable -->
    <xsl:variable 
          name="consideration" 
          select="ext:CreateOrderLine
        ($order-id, @product, number(@quantity), number(@price))" />
    
    <!-- write out processed order line -->
    <ProcessedOrderLine consideration="{$consideration}" />
    
  </xsl:template>

</xsl:stylesheet>

Conclusion

XSLT is an elegant way to query and manipulate XML data, and coupled with XSLT extensions provides a way to interface with other data stores.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Software Developer (Senior)
United Kingdom United Kingdom
Systems builder and developer, DotNet C#, Ruby, Golang, Linux, Cloud, Open Source contributor.

Comments and Discussions

 
QuestionXSLT using load image . Pin
keynagarajan18-Aug-16 3:00
keynagarajan18-Aug-16 3:00 
GeneralHi, Implementation technique required for xslt. Pin
SidharthaShenoy17-Aug-10 2:30
SidharthaShenoy17-Aug-10 2:30 
GeneralRe: Hi, Implementation technique required for xslt. Pin
Chris Stefano17-Aug-10 2:41
Chris Stefano17-Aug-10 2:41 
GeneralRe: Hi, Implementation technique required for xslt. Pin
SidharthaShenoy17-Aug-10 2:44
SidharthaShenoy17-Aug-10 2:44 
GeneralRe: Hi, Implementation technique required for xslt. Pin
Chris Stefano17-Aug-10 3:00
Chris Stefano17-Aug-10 3:00 
GeneralRe: Hi, Implementation technique required for xslt. Pin
SidharthaShenoy17-Aug-10 3:13
SidharthaShenoy17-Aug-10 3:13 
GeneralRe: Hi, Implementation technique required for xslt. Pin
Chris Stefano17-Aug-10 3:37
Chris Stefano17-Aug-10 3:37 
Generalthanks Pin
stefano piuri24-Apr-07 5:14
stefano piuri24-Apr-07 5:14 
GeneralThanks &amp; Engines Pin
Code Monkey1-Feb-07 5:41
Code Monkey1-Feb-07 5:41 
GeneralRe: Thanks &amp; Engines Pin
Chris Stefano1-Feb-07 6:25
Chris Stefano1-Feb-07 6:25 
Questionwhat about performance Pin
Member 237274018-Jan-07 23:44
Member 237274018-Jan-07 23:44 
AnswerRe: what about performance Pin
Chris Stefano19-Jan-07 0:23
Chris Stefano19-Jan-07 0:23 
GeneralEsoteric but very interesting Pin
TGolden17-Jan-07 4:35
TGolden17-Jan-07 4:35 
GeneralRe: Esoteric but very interesting Pin
Chris Stefano17-Jan-07 6:04
Chris Stefano17-Jan-07 6:04 
GeneralGreat Article! Pin
Stephen Brannan12-Jan-07 10:50
Stephen Brannan12-Jan-07 10:50 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.