|
YOUR FEEDBACK Did you read today's front page stories & breaking news?
SYS-CON.TV |
TODAY'S TOP SOA & WEBSERVICES LINKS XML Programming & Design: How to Reduce the Burden on Web Designers
Leveraging designer tag libraries
By: Peter Horsfield
Apr. 30, 2004 12:00 AM
The whole point of teams is to allow different specialties to complement one another and achieve the extraordinary, so it can only be a good thing to reduce the barriers between them. This article shows how to eliminate the interdependency between HTML design skills and XML processing. XML is being applied on all business fronts for internal and external data exchange, transcoding between domains, archival, and powering dynamic and sometimes real-time Web sites. Yet all this technological weaving ties together more than just data; there's also a human aspect. Engineers trade schemas and specifications between one another, and each engineer is expected to understand and be able to integrate those specifications. This, of course, is an accepted facet of our lives, but it belies a problem. As XML usage has grown ubiquitous, so has this web of dependency. First between software engineering and data modeling specialties, and lately into design fields such as Web design. Designers are increasingly required to integrate Web page designs with presentation of XML data sources. This has created a market opportunity for tools such as Altova's Stylevision product. Stylevision is a singular achievement that allows a Web designer to visually craft data-driven Web pages, with the end result being not HTML but instead an XSLT style sheet capable of transforming XML instance data into the desired page. Thus, software is provided to hide the increasing complexity of the design task (see Figure 1). All server-side languages, from Perl CGI scripts to Python, provide a means to embed data in a page (see Figure 2). However, all these languages are deficient in their ability to separate the work of the designer from that of the Web programmer. The inventors of XSLT recognized that creating HTML from other forms of XML data would be a powerful tool and gave us the simplified model of XSLT. Neither the simplified model nor the full-blown version alter the notion that there is a single file that contains both transformation and presentation elements. The remainder of this article will show that XSLT can be used to elegantly separate the concerns of the programmer while supporting those of the designer. The GoalInitially, server-side HTML consisted of procedural code placed in blocks that were somehow escaped out of a regular HTML document. With the advent of XML and XHTML, the trend has been toward using new tags similar in appearance to HTML. The HTML is still well formed.We'll build a similar tag library using XSLT. A transformation file will be created that can be applied to merge an HTML presentation document with an XML data document. Any tags used in the HTML document will be replaced according to the design of the tag library. If no tags are used in the HTML document, the output will be similar to the input. Furthermore, the tag library will be domain specific and thus meaningful to the Web designer. Reasons for Using XSLTBy limiting the data source to an XML document, we lose all the flexibility of the general-purpose tag libraries, but in return we also gain many benefits. Designers will find this XSLT-based solution easier to use than the other server-side solutions because:
Our solution does not come with the baggage associated with embedding a general-purpose language. The simplicity of Listing 3 as compared with Listings 1 (PHP) and 2 (JSP/JSTL) is gained by moving all the logic into the XSLT style sheet. Listings 1-10 can be downloaded from www.sys-con.com/xml/source.cfm. (Listing 3 is well formed but not valid because XHTML documents contain only XHTML markup. After undergoing the XSLT transformation we are going to create, it will be valid, too.) Any server-side solution that requires a single document to contain configuration or general-purpose code will suffer this bloating to some extent. The distinction is more obvious when using the verbose DOM extensions in PHP4 than when using others. In fact, the PHP page must also load the data XML document to process, but I omitted that for brevity. The XSLT-driven form offers the designer a level of legibility by default that is far greater than that offered by a general-purpose server-side scripting language. WYSIWYG IDE integration Macromedia Dreamweaver allows you to add custom tag libraries through the Tag Library Editor (see Figure 4). Each tag can be manually added to Dreamweaver, or one of the many tag library file types can be imported. This includes support for loading XML Schemas. Accessing Live DataThe document() function is implemented by the major XSLT processors (at least Saxon, Xalan, and Microsoft's). It allows an XSLT transformation to access XML outside of its primary input. The document function acts as an alternative root in XPath expressions and can even be assigned to variables. I highly recommend using the document function to load a top-level variable, and then referencing the variable elsewhere. In XSLT processors that load the entire target URI, this ensures that only one access is made - a major optimization.Working locally "Product Name {product}. Price is ." After the transformation, "{product}" would be replaced with the actual product name. Testing locally The same XSLT transformation that would execute on the server side can be performed with the command-line modes of tools such as Saxon or Xalan. For a more user-friendly approach, many XML-aware IDEs (e.g., Borland and Altova) allow you to configure transformation scenarios that can be applied with just a few clicks. Leveraging XML/XSLT accelerators Implementing an XSLT Tag LibraryFigure 3 shows the designer segregated from coding and data-modeling tasks, and left dealing with only our design schema, an artifact of the coding effort. The data and design schemas are elevated to true contracts between specialties.The design schema specifies the set of designer- and domain-oriented tags available. To add live data to a document, the designer would just drop in one of these tags. At some point we perform an XSLT transformation that removes those tags and replaces them with actual data. Our task in this article is to create the merge.xslt file that will perform the replacements. To continue we're going to need some live data. You'll find that Listing 4 shows a simple XML file containing some neat facts about the solar system. (An XML Schema for this file is available at www.sys-con.com/xml/sourcec.cfm.) Simple XSLT CopyingWhen an XHTML page is fed into a style sheet with no templates, the input is stripped of all elements and only text content is output. So the first step is to create a style sheet that performs a copy without modifying the document, at least not functionally. (The page is completely rewritten by the transform, so some minor changes may be experienced as an artifact of this process.)Listing 5 shows an XSLT style sheet for copying XHTML. The <xsl:output/> tag causes the XSLT processor to indent the output and to represent the output as a strict XHTML document (this only affects the document type processing instruction). The single template matches attributes and any node, and copies it to the output stream as we require. This copier is the foundation upon which we will build our data-merging system. Replacing Designer TagsThe next step is to intercept those tags in the input that we're interested in. Our designer tags are distinguished from XHTML tags through the namespace to which they are assigned, so we add these namespaces to the style sheet. Now we can create a new template that will react to one of these designer tags. We'll pick a simple one to start with, an element that inserts a copyright string into the output.This modification will cause any copyright tags (which must be in the namespace http://xml.grumpykitty.biz/designer/stars/1.0) to be replaced with the copyright string (C) 2004 Grumpy Kitty Productions. The XSLT document() function is used to access our data source. We must remember to add the data namespace to the style sheet. Listing 7 shows a full style sheet that disregards its input and instead outputs the number of planets in the Sol system. The style sheet is decoupled from the source by passing in the URI as a style sheet parameter. This allows us to maintain Sol system data for multiple universes. This style sheet will ignore any of its standard input and merely output the number of planets. Here is a sample command line for Xalan: java org.apache.xalan.xslt.Process Listings 5, 6, and 7 are easily combined to copy XHTML documents, replacing designer elements with live data. Tags Within TagsThe complexity arrives when we try to represent relationships within the data set. We could specify separate tags for Star n, Planet n, Moon n, and so on. More realistically, we can provide tags for the designer that represent repeating elements in the source data. Whereas previously our designer tags were replaced with real data, these tags are not replaced with anything. They serve only to identify portions of the template XHTML page that should be duplicated for every data point. I call these tags grouping nodes.Given this XHTML fragment: <body><ul> The intent is that all of the tags within the <star:planetGroup/> should be duplicated for each planet in the input data. This includes both XHTML and designer tags. Grouping ImplementationEvery time we reach such a grouping node in the template XHTML, we must duplicate the entire contents of the grouping node for each matching data point. However, the grouping node itself should not be copied.Iteration over the source data is performed with the <xsl:for-each/> element as shown in Listing 8. Note: The standard "dot" operator is overridden by the <xsl:for-each/> element. To work around this, I store the current node (i.e., the <star:planetGroup/> node in the XHTML document) in a local variable. The duplication performed by <xsl: apply-templates/> is different because we must first lose the <star:planetGroup/> node and record the current data point from the source data. We can do the first by creating a separate template that just skips the <xsl:copy/> element and specifies mode="ignore". Preserving the current source context is a little more complicated. The XHTML document being copied is arbitrarily deep, and we cannot use top-level variables for this purpose because parameters and variables in XSLT are immutable. Instead, we pass the current source context node(s) as one or more template parameters to every copying or grouping operation. Grouping nodes can then use variable hiding to specify new contexts. Listing 9 shows this technique in action. Groups Within GroupsThere are at least three semantic groups within our source data: stars, planets, and moons. Each of these groups must be maintained with <xsl:with-param /> and <xsl:param /> pairs. This must happen during the copy and during <xsl:for-each/> iterations.The notion that moons are tied to planets, and that planets are nested within star systems, is embodied by the declaration of the <xsl:for-each/> element. Just as we can iterate over the contents of the document top-level variable, we can also iterate using the variables holding our context. Listing 10 shows such a template for the <stars:moonGroup /> grouping node. The following code sample shows a leaf template that places the orbit of the current moon into the output by referencing the newly established moonGroup parameter. <xsl:template match="designer:moonGroup//designer:orbit"> In this implementation it is very easy to add new leaf designer tags, and a little more complicated to add new groups. From the designer's standpoint, some of the XHTML is simply wrapped in a new, obviously custom, tag. When viewed after the transformation, the XHTML has been duplicated as many times as there are data points. This lends itself very well to building XHTML tables, lists, and so on. Simplifications and OptimizationsSkipping XSLT template parametersI've mentioned that all grouping and copying nodes must take the group parameters and pass them through. This is only the case if they are needed further down the XHTML tree. For the closest parent grouping node to a simple designer tag, this is almost certainly true. On the other hand, these simple designer tags may only need to access one of the several parent groups. Not every little piece of information about the moon needs to reference the earth! Reusing designer tags This result can be obtained by:
When processing reaches our designer tags, the latestGroup parameter always contains the correct node in the source data and is simple to use: <xsl:template match="designer:name"> In the source distribution, you'll find examples of all three solutions. Potential IssuesThe primary issue with this solution is speed. XSLT transformations can easily create a bottleneck, and this solution uses XSLT extensively. If your data is rapidly changing, I recommend using a hardware accelerator or another solution. I highly recommend creating unit tests that enforce timings during development.Also, the document function steps outside the bounds of the XSLT environment. This may expose you to nuances of the host environment. Ensure that your host environment and the XSLT processor play nicely together. IntegrationThe main purpose of this article is to alleviate work on the designer's part. To this end, the designer's tag library we created can be used within IDEs such as Macromedia's Dreamweaver. To do this, I created an XML Schema that specifies the set of designer tags; however, the schema import functionality leaves a little to be desired. A workaround is to create a mock tag library descriptor file (.tld) that can be imported. It's also possible to create an XSL transform to perform this conversion.Download the source distribution to find the dreamweaver.tld file and follow these steps inside Dreamweaver:
Other XML-enabled IDEs and production environments should be similarly capable of integrating this solution. Looking ForwardIn this article I have described a method to offload work from the page designer onto the back-end developers. We used standard XSLT to simplify a designer's access to live data.The additional layer of separation can be used to perform calculations outside of the page design and data model, to isolate the designer from data changes, and to allow for unit testing. Although we focused on creating new designer-oriented tag libraries, the core data-merging techniques are applicable to processing any XML document, and even any tag. One particularly cool application I wrote using these techniques deals with manipulating an SVG drawing at publish time based on a dynamic XML data feed. I'm sure many of you will be able to blow that away with your own ideas! Feel free to e-mail to me with your comments and observations. A full implementation of this technique and supporting files for ANT, JAXB, Eclipse, Dreamweaver, and Apache Cocoon is available for download at http://xml.grumpykitty.biz. ReferenceYOUR FEEDBACK
XML JOURNAL LATEST STORIES . . .
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK BREAKING XML NEWS |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||