.NET
  Home arrow .NET arrow Page 9 - Outputting Code
ASP Free Forums 
.NET  
ASP  
ASP Code  
ASP.NET  
ASP.NET Code  
BrainDump  
C#  
Code Examples  
Database  
Database Code  
IIS  
Microsoft Access  
MS SQL Server  
Visual Basic.NET  
Windows Scripting  
Windows Security  
XML  
ASP Web Hosting  
ASP.NET Web Hosting 
Mobile Linux 
App Generation ROI 
Windows Web Hosting
 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
.NET

Outputting Code
By: Apress Publishing
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 3 stars3 stars3 stars3 stars3 stars / 5
    2004-10-04

    Table of Contents:
  • Outputting Code
  • Understanding Script Directives
  • Understanding Other Features of the Generation Harness
  • Extending the Harness
  • Examining Code Generation Mechanics
  • Exploring Details of XSLT Code Generation
  • Creating Named Templates
  • Creating Match Templates
  • Supporting Stylesheets
  • Exploring Details of Brute-Force Generation
  • Creating a Class
  • Creating the Support Template
  • Understanding Types
  • Building a CodeDOM Graph
  • Building the Code Structure
  • Outputting Assignments
  • Creating Arrays
  • Exploring Other Features
  • Working with the CodeDOM

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Outputting Code - Supporting Stylesheets


    (Page 9 of 19 )

    Supporting stylesheets allow you to isolate generic templates that you can reuse in different XSLT stylesheets. For example, the SimpleDataContainer.xslt stylesheet uses the NewLine template in the Support.xslt file. Using this template doesn’t save much typing, but it keeps you (and later programmers) from having to remember the hexadecimal values of the carriage-return and line-feed characters:

    <xsl:template name="NewLine">
      <xsl:text> </xsl:text>
    </xsl:template>

    As another example, you’ll frequently need to control commas in lists. This is an example of when you might need to output this:

    {0, 1, 2}

    You can control the comma at the beginning or the end of the list, but the CommaIfNotFirst template is theoretically more efficient than CommaIfNotLast:

    <xsl:template name="CommaIfNotFirst">

      <xsl:if test="position()!=1">, </xsl:if>

    </xsl:template>

    <xsl:template name="CommaIfNotLast">

      <xsl:if test="position()!=last()">, </xsl:if>

    </xsl:template>

    NOTE: XPath has a number of useful functions. If you have trouble finding references to them in the .NET Help, look up the “xslt, reference” section in the index. This will get you into the fairly good XSLT documentation. Appendix A also discusses XPath functions.

    The SimpleDataContainer.xslt stylesheet uses the FileOpen template in Support.xslt to supply a consistent header at the top of the output files, which you can adjust to your liking. When you make a change, the change will appear in all stylesheets importing or including Support.xslt. This template needs to run as part of a stylesheet that has the fileName stylesheet parameter or variable. If not run with this available, you’ll get XSLT errors. If you aren’t sure this parameter will be available, explicitly pass it as a template parameter because not passing a template parameter isn’t considered an error. Accessing a variable that doesn’t exist, however, is an XSLT error.

    The FileOpen template outputs standard Option Strict, Option Explicit, and Imports System statements into your output file’s header. The imports parameter passes additional imports as a comma-delimited string. The named template RecursiveImports breaks this string down and outputs the Imports statement. The template then outputs a comment block containing the filename:

    <xsl:template name="FileOpen">
    <xsl:param name="imports" />
    Option Strict On
    Option Explicit On
    Imports System
    <xsl:call-template name="RecursiveImports">
    <xsl:with-param name="imports" select="normalize-space($imports)"/>
    </xsl:call-template>
    #Region "Description"
    ' <xsl:call-template name="StripPath">
    <xsl:with-param name="fname" select="$fileName" />
    </xsl:call-template>
    #End Region
    </xsl:template>

    TIP: You could include the generation date and time, but that would cause source control to always see the file as new and unnecessarily mark the file as changed. Because of this complication, I suggest you don’t include the date and time in the header.

    Using Recursive Templates

    How do you break down a comma-delimited string if you can’t reassign the values of variables? You use a recursive template that creates a new variable every time you call it. This is an advanced aspect of XSLT that can be handy at times. String manipulation such as the previous two samples is a convenient place to use recursive templates. The RecursiveImports template outputs an Import statement for each namespace in a comma-delimited list:

    <xsl:template name="RecursiveImports">
    <xsl:param name="imports"/>
    <xsl:variable name="remaining" select="substring-after($imports,',')"/>
    <xsl:choose>
    <xsl:when test="string-length($remaining) > 0">

    Imports <xsl:value-of select="normalize-space(substring-before($imports,','))"/>
    <xsl:call-template name="RecursiveImports">
    <xsl:with-param name="imports" select="$remaining"/>
    </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
    Imports <xsl:value-of select="normalize-space($imports)"/>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:template>
     

    TIP: I included this example so you have a reference of when you need recursion. Don’t worry if you get a little lost in it—you don’t need to use recursion often.

    The imports parameter contains the comma-delimited string. The template creates a new variable named remaining that contains everything after the first comma. An xsl:choose directive tests whether the remaining variable contains anything. The remaining variable would be empty if the imports parameter ended with a comma or didn’t contain a comma. If the remaining variable isn’t zero length, the template outputs an Imports statement with the contents before the comma. The normalize-space XPath function is basically the same as the .NET String class’s Trim method. After outputting the Imports statement, the template calls itself, passing the contents of the $remaining variable as the imports parameter. This effectively calls the RecursiveImports for every item in the comma-delimited string, with the imports parameter chopped off at the first comma each time. The last time it’s called, the imports parameter contains no comma, the xsl:otherwise directive is processed, and the template simply outputs the Imports statement.

    The trick to creating recursive templates (or using recursion in any language) is to provide a clear end to the recursion. In this case, you chop off string elements until there’s no comma left. If you fail to provide this clear end point, the recursion is endless, or unbounded.

    TIP: When processing XSLT in .NET, if you encounter endless recursion, your application will appear to freeze up (the action will take significantly too long). If the debugger is running, you can break using Ctrl+Break and end the process.

    You can use the same approach to strip a path off a full filename, resulting in just the filename. In the file header, the name of the file is useful. The directory where you generate it may not be its permanent location, so it isn’t included. The StripPath template is otherwise similar to the RecursiveImports template:

    <xsl:template name="StripPath">
    <xsl:param name="fname"/>
    <xsl:variable name="remaining" select="substring-after($fname,'&#x5c;')"/>
    <xsl:choose>
    <xsl:when test="string-length($remaining) > 0">
    <xsl:call-template name="StripPath">
    <xsl:with-param name="fname" select="$remaining"/>
    </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="$fname"/>
    </xsl:otherwise>
    </xsl:choose>
    </xsl:template>
     

    NOTE: &#x5c; is the escape sequence for the backslash character. You have to escape the backslash in at least some cases.

    Capping Off XSLT Code Generation

    The previous sections took XSLT code generation out of the theoretical to show how you can use it in the real world with advanced XSLT techniques. To make XSLT code generation easy, you’ll want to use the following:

    • A single entry-level template accessing the root

    • A single high-level processing template called in the context you’re processing

    • A named template (xsl:call-template) for each region in the output after you organize your sample code into regions

    • Additional nested named and match templates (xsl:apply-templates) as regions become longer and more complex

    • xsl:value-of for inserting values

    • xsl:if when a conditional block has only one option and xsl:choose when there are multiple conditional blocks

    • Match templates for any looping elements unless the output is nearly trivial, in which case you should use an xsl:for-each

    • A separate supporting stylesheet to contain reusable utility templates

    You’ll see more samples of XSLT code generation throughout the book. I use it for examples because it’s more concise than the other code generation mechanisms. 

    This chapter is from Code Generation in Microsoft .NET by Kathleen Dollard (Apress, 2004, ISBN: 1590591372). Check it out at your favorite bookstore today.

    Buy this book now.

    More .NET Articles
    More By Apress Publishing


     

    .NET ARTICLES

    - Using CrystalReportViewer to Display Crystal...
    - Creating Summary .Net Crystal Reports
    - More on Commands, Input and the WPF
    - Grouping and Aggregating When Querying LINQ ...
    - Commands, Input and the WPF
    - Keyboard and Ink Input with WPF
    - Mouse Input and the WPF
    - Input with Windows Presentation Foundation
    - Introducing LINQ with XML and Databases
    - An Introduction to LINQ
    - Querying LINQ to SQL: Basics
    - Completing a Simple Storefront with LINQ
    - Knowing Your Environment: the System.Environ...
    - Creating the Home Page for a Simple Storefro...
    - LINQ Quickly with Language Integrated Queries





    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 3 hosted by Hostway
    Stay green...Green IT