tags:

views:

812

answers:

6
+8  Q: 

XSLT Abstractions

I'm exploring the XML -> XSLT -> HTML meme for producing web content. I have very little XSLT experience.

I'm curious what mechanisms are available in XSLT to handle abstractions or "refactoring".

For example, with generic HTML and a service side include, many pages can be templated and decomposed to where there are, say, common header, nav, and footer segments, and the page itself is basically the body.

The common markup languages, JSP, PHP, ASP, go as far as to allow all of those segments to have dynamic content (such as adding the user name to every header block).

JSP goes even farther by allowing you to create Tag files, which can accept arguments to be used when generating the content, and even surround and work on content within the tags themselves.

I'm curious similar functionality is done within XSLT. What facilities are there to make reusable block of XSLT for things like creating HTML pages?

+6  A: 

Templates, Includes.

Xsl is very different from any other programming language. Its rule based.

I recommend you to read something about Xslt and then ask a bit more spedific.

Andre Bossard
All of the tutorials and such that I've seen deal with XSLT "in the small", focusing on syntax etc. This is more of "now that I know how to use it, how do I actually apply it" kind of question.
Will Hartung
+2  A: 

There are both xsl Include and Import statements that you can use to abstract away portions of the page. XSLT itself is very much the kind of thing that can reproduce tag file type behavior. You edit your xml data files with the tags you want. Meanwhile, your xsl templates are going to know what do to with those tags then they encounter them.

mspmsp
+2  A: 

You can give templates names and then call them via 'call-template'

In XSLT 2.0 you can create your own functions (although I find the syntax tortuous)

A wonderful area to explore is using XSLT to generate XSLT stylesheets. This lets you automate common conversion scenarios where 90% of the stylesheet is boilerplate. In order to do this you need to become familiar with 'namespace-alias'. Its a great way to expand your knowlege of the language.

Garth Gilmour
It took me a shower to figure out what you were saying here about XSLT -> XSLT, but I finally groked it. That's very clever as well. If XSLT isn't abstract enough for you, since it's just XML, make it more abstract. "Will write code that writes code that writes code for food" as they say. Thank you.
Will Hartung
No worries - let me know if you would like an example
Garth Gilmour
+11  A: 

For my own project, this is how I divided up my pages. There was a template.xsl file which was imported by each of my XSLs. Most pages just had template.xsl, but some pages such as cart, etc. needed their own because of the different kind of data they were parsing.

<page title="Home">
    <navigation>
        <!-- something here -->
    </navigation>
    <main>
        <!-- something here -->
    </main>
</page>

This is a snippet from my template.xsl. I threw in all the common stuff in here, and then gave the opportunity for my pages to add their own information through call-template.

<xsl:template match="/page" name="page">  
    <html>
    <head>  
        <title><xsl:value-of select="(@title)" /></title>           
        <xsl:call-template name="css" />
        <xsl:call-template name="script" />
    </head>
    <body>
        <xsl:call-template name="container" />
    </body>
    </html>
</xsl:template>

An example of how my css tag would respond. Note that it calls css-extended. css only had the the common css' that would apply across all pages. Some pages needed more. Those could override css-extended. Note that is needed because call-template will fail if a page calls a template but doesn't define it anywhere.

   <xsl:template name="css">
        <link rel="stylesheet" type="text/css" href="{$cssPath}reset.css"  />
     <link rel="stylesheet" type="text/css" href="{$cssPath}style.css"  />
        <link rel="stylesheet" type="text/css" href="{$cssPath}layout.css" />
        <xsl:call-template name="css-extended" />
    </xsl:template>   

    <!-- This is meant to be blank. It gets overriden by implementing stylesheets -->
    <xsl:template name="css-extended" />

My container would work in a similar manner-- common stuff was defined and then each page could just provide an implementation. A default implementation was in the XSL. (in content)

  <xsl:template name="container">
        <div id="container">
            <xsl:call-template name="header" />
            <xsl:call-template name="content" />
            <xsl:call-template name="footer" />
        </div>
    </xsl:template>  

    <xsl:template name="content">
        <div id="content">
            <div id="content-inner">
                <xsl:call-template name="sideBar" />
                <xsl:call-template name="main" />
            </div>
        </div>
    </xsl:template>   

    <xsl:template name="main">
        <div id="main">
            <xsl:apply-templates select="main" />
            <xsl:call-template name="main-extended" />
       </div>
    </xsl:template>

    <!-- This is meant to be blank. It gets overriden by implementing stylesheets -->
    <xsl:template name="main-extended" />

<xsl:template name="footer">
     <div id="footer">
        <div id="footer-inner">
        <!-- Footer content here -->
        </div>
     </div>
</xsl:template>

It worked quite beautifully for me. If there are any questions I can answer for you, let me know.

Swati
This is excellent and exactly what I was looking for, thank you.
Will Hartung
I like this answer. A small more information: if you want to put some of the templates in external files, one possible solution is Xinclude <http://www.w3.org/TR/xinclude/>
bortzmeyer
+1  A: 

XSLT is powerful, but it is very different from most programming languages and it is quite limited in what it makes available to you, so things that you have built-in with another language may need some quite complex xsl manipulation to work with. I found the cheatsheet from here useful when I was going through a lot of XSLT work a couple of weeks back.

Don't expect that XSLT will do things in a particular way and you probably can find good ways of doing those things, but if you have too much of a set idea about how something should work it's easy to get stuck.

glenatron
That's always the challenge. You take your prior experience and try to apply it to something new. I know XSLT has a different view of the world, but I also knew folks had to solve similar problems with it, and I was curious how they went about it.
Will Hartung
+2  A: 

XSL is based on templating.

XML data can be "re-used" at three-levels. At the most basic level you can <xsl:for-each /> through XML.

Note: For-each in XSL is not looping through the data, it's just matching the data. Also when your "inside" a for-each your inside that "context" of the XML (which is like the concept of "scope" in programming)

An example of using and re-using a for-each

<xsl:for-each select="/xml/data/here">
    ... do some stuff ...
</xsl:for-each>
<xsl:for-each select="/xml/data/here">
    ... do some DIFFERENT stuff ...
</xsl:for-each>

The for-each nodes are contained within template nodes (2nd level of reuse). There are two types of template nodes: Match and Named. Match template nodes, act like the for-each node mentioned above, but are automatically called by the template engine if any nodes are matched when XSL processing starts. Match template nodes can also be explicitly applied. On the other hand Named template nodes are always explicitly applied and can be thought of as like functions.

Example of a Match template which will Always be called (because a root node will always exist)

<xsl:template match="/">
    ... do some stuff ...
</xsl:template>

A Match template calling another match template explicitly

<xsl:template match="/">
    <xsl:apply-templates select="xml/data/too" />
</xsl:template>

<xsl:template match="xml/data/too">
     ... do something ...
</xsl:template>

Note: In order for the Match template to work, the XML Node it is matching needs to exist. If it doesn't there is no match, so that template is not called.

Example of a Named template

<xsl:template name="WriteOut">
    ... data with NO Context Here ...
</xsl:template>

Or calling a Named template from a Matched template

<xsl:template match="/">
   <xsl:call-template name="WriteOut" />
<xsl:template>

Note: You can mix and match where you call matched and named templates from, you just have to watch what context you are in.

All of template nodes are held in XSL Stylesheets, and you can include and import various stylesheets. For example you can hold all of the templates dealing with HTML header nodes in one template and all of the templates dealing with the HTML body nodes in another. Then you can create one stylesheet that includes both Header and Body stylesheets.

Example of an include node

<xsl:include href="header.xsl" />

In conclusion there are three ways to abstracting chunks of data, through for-eaching, through templating or through including stylesheets.