Specializing your stylesheets with xsl:import

Specializing your stylesheets with xsl:import

Introduction

XSLT has a very powerful and cool feature that doesn't seem to be that well known: The ability to import other stylesheets into the stylesheet you're working on. Why is this a big deal, you ask? Mainly because it presents an elegant solution to an oft seen problem: How to create a slight variation on an existing mapping program without copying the entire program and modifying the copy.

What was the problem again?

Imagine a scenario in which you want to deliver electronic invoices to your customers. You've created a mapping program that transforms an INVOIC02 IDoc into an XML format. Everything works smoothly, until one day a new, important customer requests a slight change to the element:

<InvoicingParty>
    <VendorNumber>01061854</VendorNumber>
    <VendorName>Watson and Holmes Enterprises</VendorName>
    <VendorAddress>
        <Street>221b Baker Street</Street>
        <City>London</City>
        <PostalCode>NW1 6XE</PostalCode>
    </VendorAddress>
</InvoicingParty>

The customer requests that the vendor's name and number be combined into a single element:

<InvoicingParty>
    <Vendor number="01061854">Watson and Holmes Enterprises</Vendor>
    <VendorAddress>
        <Street>221b Baker Street</Street>
        <City>London</City>
        <PostalCode>NW1

    Requires Free Membership to View

    When you register, you will start receiving targeted emails from my award-winning team of editorial writers. Our goal is to keep you informed on the hottest topics and biggest challenges faced by SAP professionals today.

    Hannah Smalltree, Editorial Director

    By submitting your registration information to SearchSAP.com you agree to receive email communications from TechTarget and TechTarget partners. We encourage you to read our Privacy Policy which contains important disclosures about how we collect and use your registration and other information. If you reside outside of the United States, by submitting this registration information you consent to having your personal data transferred to and processed in the United States. Your use of SearchSAP.com is governed by our Terms of Use. You may contact us at webmaster@TechTarget.com.

6XE</PostalCode> </VendorAddress> </InvoicingParty>

XSLT to the rescue

What we'd like to do is create a new mapping program that is a specialization of the existing one. In object-oriented terms, we'd like to inherit the parent program's functionality and override a small subset of it. Using message mapping, such specialization is not possible and we'd have to resort to copying the entire mapping program and modifying the copy. Using XSLT, however, specialization is not only possible, but also very simple to implement.

The following is a snippet of the Invoice_general.xsl stylesheet, which transforms an entire INVOIC02 IDoc into the invoice XML format. Specifically, the template shown is responsible for creating the invoice header:

<xsl:template name="InvoiceHeader">
    <Header>
        <InvoiceNumber>....</InvoiceNumber>
        <InvoiceDate>....</InvoiceDate>
        <Currency>....</Currency>
        <!-- Lots of other header information goes here -->
        <xsl:call-template name="InvoicingParty"/>
    </Header>
</xsl:template>

Notice that the template doesn't know how to format the invoicing party. Instead, it delegates that task to the InvoicingParty template:

<xsl:template name="InvoicingParty">
    <xsl:variable name="party" select="/INVOIC02/IDOC/E1EDKA1[PARVW='RS']"/>
    <InvoicingParty>
        <VendorNumber>
            <xsl:value-of select="$party/LIFNR"/>
        </VendorNumber>
        <VendorName>
            <xsl:value-of select="$party/NAME1"/>
        </VendorName>
        <VendorAddress>
            <Street>
                <xsl:value-of select="$party/STRAS"/>
            </Street>
            <City>
                <xsl:value-of select="$party/ORT01"/>
            </City>
            <PostalCode>
                <xsl:value-of select="$party/PSTLZ"/>
            </PostalCode>
        </VendorAddress>
    </InvoicingParty>
</xsl:template>

Using XSLT templates we've managed to pinpoint exactly where to implement the customer's request. We still haven't seen how to actually implement it, though.

Adding the xsl:import magic

Using the XSLT <xsl:import> element, we can import another stylesheet into the stylesheet we're working on. The true power of this feature lies in the fact that templates in the imported stylesheet can be overriden by templates in the importing stylesheet. Here's a complete stylesheet that implements the customer's request:

xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:import href="Invoice_general.xslt"/>

    <xsl:template name="InvoicingParty">
        <xsl:variable name="party" select="/INVOIC02/IDOC/E1EDKA1[PARVW='RS']"/>
        <InvoicingParty>
            <Vendor number="{$party/LIFNR}">
                <xsl:value-of select="$party/NAME1"/>
            </Vendor>
            <VendorAddress>
                <Street>
                    <xsl:value-of select="$party/STRAS"/>
                </Street>
                <City>
                    <xsl:value-of select="$party/ORT01"/>
                </City>
                <PostalCode>
                    <xsl:value-of select="$party/PSTLZ"/>
                </PostalCode>
            </VendorAddress>
        </InvoicingParty>
    </xsl:template>

</xsl:stylesheet>

The new stylesheet, Invoice_specific.xsl, imports the general stylesheet and implements only the single template that's needed to accommodate the customer's request. The same result could have been achieved by making a physical copy of the general stylesheet and modifying the InvoicingParty template. That would lead to potentially massive amounts of duplicated code, though. The proposed solution contains no duplicated code whatsoever. The specialized stylesheet is also very compact and it's immediately obvious how it extends the general stylesheet. Furthermore, bug fixes and improvements in the general stylesheet will automatically trickle down to the specialized stylesheet.

Final thoughts

In my opinion, the element belongs in the toolbox of every XSLT developer. It offers a powerful and clean solution to a problem often faced by XI developers, namely creating a variation on an existing mapping program without resorting to copying it and modifying the copy. For more information on the element, please refer to the "Stylesheet Import" section of the W3C XSLT 1.0 recommendation.


This content is reposted from the SAP Developer Network.
Copyright 2006, SAP Developer Network

SAP Developer Network (SDN) is an active online community where ABAP, Java, .NET, and other cutting-edge technologies converge to form a resource and collaboration channel for SAP developers, consultants, integrators, and business analysts. SDN hosts a technical library, expert blogs, exclusive downloads and code samples, an extensive eLearning catalog, and active, moderated discussion forums. SDN membership is free.

Want to read more from this author? Click here to read Morten Wittrock's weblog. Click here to read more about SAP Exchange Infrastructure (XI) on SDN.



This was first published in September 2006

Join the conversationComment

Share
Comments

    Results

    Contribute to the conversation

    All fields are required. Comments will appear at the bottom of the article.

    Disclaimer: Our Tips Exchange is a forum for you to share technical advice and expertise with your peers and to learn from other enterprise IT professionals. TechTarget provides the infrastructure to facilitate this sharing of information. However, we cannot guarantee the accuracy or validity of the material submitted. You agree that your use of the Ask The Expert services and your reliance on any questions, answers, information or other materials received through this Web site is at your own risk.