Click here to Skip to main content
Licence 
First Posted 11 Jan 2007
Views 30,320
Downloads 215
Bookmarked 49 times

XSLT Unleashed

By | 11 Jan 2007 | Article
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.

// 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.

<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

About the Author

Chris Stefano

Software Developer (Senior)

South Africa South Africa

Member

I'm a developer specializing in software for the financial services industry particularly in the decision support area. Currently my specialty is in investment compliance.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralHi, Implementation technique required for xslt. PinmemberSidharthaShenoy2:30 17 Aug '10  
GeneralRe: Hi, Implementation technique required for xslt. PinmemberChris Stefano2:41 17 Aug '10  
GeneralRe: Hi, Implementation technique required for xslt. PinmemberSidharthaShenoy2:44 17 Aug '10  
GeneralRe: Hi, Implementation technique required for xslt. PinmemberChris Stefano3:00 17 Aug '10  
GeneralRe: Hi, Implementation technique required for xslt. PinmemberSidharthaShenoy3:13 17 Aug '10  
GeneralRe: Hi, Implementation technique required for xslt. PinmemberChris Stefano3:37 17 Aug '10  
Generalthanks Pinmemberstefano piuri5:14 24 Apr '07  
GeneralThanks & Engines PinmemberCode Monkey5:41 1 Feb '07  
GeneralRe: Thanks & Engines PinmemberChris Stefano6:25 1 Feb '07  
Questionwhat about performance PinmemberMember #237274023:44 18 Jan '07  
AnswerRe: what about performance PinmemberChris Stefano0:23 19 Jan '07  
GeneralEsoteric but very interesting PinmemberTGolden4:35 17 Jan '07  
GeneralRe: Esoteric but very interesting PinmemberChris Stefano6:04 17 Jan '07  
GeneralGreat Article! PinmemberKinStephen10:50 12 Jan '07  

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

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.5.120517.1 | Last Updated 11 Jan 2007
Article Copyright 2007 by Chris Stefano
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid