210 likes | 313 Views
Advanced XSL. Learn how to use advanced XSLT techniques, EXSLT, and Xalan extensions to solve complicated problems. Agenda. XSL & XSLT XSLT Warmup Muenchian Method EXSLT Xalan Extensions Velocity Script Formats. XSL & XSLT.
E N D
Advanced XSL Learn how to use advanced XSLT techniques, EXSLT, and Xalan extensions to solve complicated problems. Amy Liu & Brett Goodwin
Agenda XSL & XSLT XSLT Warmup Muenchian Method EXSLT Xalan Extensions Velocity Script Formats Amy Liu & Brett Goodwin
XSL & XSLT • XSL (eXtensibleStylesheetLanguage) consists of three parts: • XSLT a language for transforming XML documents • XPath a language for navigating in XML documents • XSL:FO a language for formatting XML documents Amy Liu & Brett Goodwin
http://www.w3schools.com/xsl/xsl_w3celementref.aspXSLT Warmup • <xsl:templatematch=“xpath-expression”></xsl:template> • <xsl:value-of select=“xpath-expression”/> <xsl:copy-of select=“xpath-expression/node()”/> • <xsl:call-templatename=“template-name"/> <xsl:apply-templatesselect=“xpath-expression”/> <xsl:for-each select=“xpath-expression”></xsl:for-each> • <xsl:iftest=“expression=‘boolean’”></xsl:if> <xsl:choose> <xsl:whentest=“expression”></xsl:when> <xsl:otherwise></xsl:otherwise> </xsl:choose> • <xsl:sort select=“xpath-expression” order=“descending”/> Amy Liu & Brett Goodwin
Using { } in place of <xsl:value-of/> <xsl:variablename=“default-page”> index</xsl:variable> <xsl:templatematch=“something”> <a> <xsl:attributename=“href”> <xsl:value-ofselect=“path”/> <xsl:text>/</xsl:text> <xsl:value-ofselect=“$default-page”/> </xsl:attribute> <xsl:value-of select="display-name"/> </a> </xsl:template> <xsl:variablename=“default-page”> index</xsl:variable> <xsl:templatematch=“something”> <a href=“{path}/{$default-page}”> <xsl:value-of select="display-name"/> </a> </xsl:template> Amy Liu & Brett Goodwin
Problem #1:Categorical Grouping… Example Scenario: You have categorized a set of pages within Cascade Server by utilizing Custom Metadata checkboxes. Now, you would like to create a listing of all the categories along with the list of pages that belong to each category in alphabetical order for display on a “Campus Resources” page. [01grouping.xml] Amy Liu & Brett Goodwin
1st Attempt:Easy-&-High-Maintenance Method <xsl:templatematch=“/system-index-block”> <h1>Campus Resources</h1> <h3>Alumni</h3> <ul><xsl:apply-templatesselect=“//system-page[dynamic-metadata[name=‘Audience’]/value = ‘Alumni’]”><xsl:sort select=“display-name”/></xsl:apply-templates></ul> <h3>Current Students</h3> <ul><xsl:apply-templatesselect=“//system-page[dynamic-metadata[name=‘Audience’]/value = ‘Current Students’]”><xsl:sort select=“display-name”/></xsl:apply-templates></ul> <h3>Prospective Students</h3> <ul><xsl:apply-templatesselect=“//system-page[dynamic-metadata[name=‘Audience’]/value = ‘Prospective Students’]”><xsl:sort select=“display-name”/></xsl:apply-templates></ul> <h3>Visitors</h3> <ul><xsl:apply-templatesselect=“//system-page[dynamic-metadata[name=‘Audience’]/value = ‘Visitors’]”><xsl:sort select=“display-name”/></xsl:apply-templates></ul> </xsl:template> <xsl:templatematch=“system-page”> <li><xsl:value-ofselect=“display-name”/></li> </xsl:template> [02grouping-attempt.xsl] Amy Liu & Brett Goodwin
Muenchian Method! <xsl:keyname=“unique-values” match=“//system-page/dynamic-metadata[name=‘Audience’]/value” use=“.”/> <xsl:templatematch=“/system-index-block”> <h1>Campus Resources</h1> <xsl:apply-templatesselect=“//system-page/dynamic-metadata[name=‘Audience’]/value[generate-id() =generate-id(key(‘unique-values’, .))]”> <xsl:sortselect=“.”/> </xsl:apply-templates> </xsl:template> <xsl:templatematch=“value”> <xsl:variablename=“currentValue” select=“.”/> <h3><xsl:value-ofselect=“.”/></h3> <ul> <xsl:for-eachselect=“//system-page[dynamic-metadata[name=‘Audience’]/value=$currentValue]”> <xsl:sortselect=“display-name”/> <li><xsl:value-ofselect=“display-name”/></li> </xsl:for-each> </ul> </xsl:template> [03muenchian.xsl] Amy Liu & Brett Goodwin
Problem #2:Truncating Content… Example Scenario: Your users are now familiar with Cascade and have created several blog posts within the system. You would like to set up some sort of landing page that features the latest blog posts. [04recent-blogs.xml] Amy Liu & Brett Goodwin
1st Option:List 3 Latest Posts + Full Content <xsl:templatematch=“system-index-block”> <xsl:apply-templatesselect=“//system-page”> <xsl:sortorder=“descending” select=“start-date”/> </xsl:apply-templates> </xsl:template> <xsl:templatematch=“system-page”> <xsl:iftest=“position() < 4”> <h3><xsl:value-ofselect=“title”/></h3> <xsl:copy-of select=“page-xhtml/node()”/> </xsl:if> </xsl:template> [05full-listing.xsl] Amy Liu & Brett Goodwin
2nd Option:Truncate using Character Count <xsl:variablename=“char-count” select=“216”/> <xsl:templatematch=“system-index-block”> <xsl:apply-templatesselect=“//system-page”> <xsl:sortorder=“descending” select=“start-date”/> </xsl:apply-templates> </xsl:template> <xsl:templatematch=“system-page”> <h3><xsl:value-ofselect=“title”/></h3> <p> <xsl:copy-of select=“substring(page-xhtml, 1, $char-count)”/> <xsl:text>...</xsl:text> </p> <p><a href=“{path}” title=“More”>More...</a></p> </xsl:template> [06truncate-charcount.xsl] Amy Liu & Brett Goodwin
3rd Option:Truncate after Whole Words <xsl:variablename=“char-count” select=“216”/> <xsl:templatematch=“system-index-block”> … </xsl:template> <xsl:templatematch=“system-page”> <h3><xsl:value-ofselect=“title”/></h3> <p><xsl:call-templatename=“parse”> <xsl:with-paramname=“unrendered”> <xsl:variablename=“truncated-result”> <xsl:call-templatename=“truncate-markup-text”> <xsl:with-paramname=“unrendered” select=“page-xhtml”/> </xsl:call-template> </xsl:variable> <xsl:value-ofselect=“substring-after($truncated-result, ‘]’)”/> </xsl:with-param> </xsl:call-template></p> <p><a href=“{path}” title=“More”>More...</a></p> </xsl:template> <xsl:templatename=“truncate-markup-text”> <xsl:paramname=“unrendered”/> <xsl:paramname=“characters-chugged” select=“number(0)”/> … </xsl:template> <xsl:templatename=“count-markup-text”> <xsl:paramname=“content”/> <xsl:paramname=“characters-chugged” select=“number(0)”/> <xsl:value-ofselect=“concat($characters-chugged + string-length($content),‘]’)”/> … </xsl:template> <xsl:template name=“get-trimmed-string”> <xsl:paramname=“string”/> … </xsl:template> <xsl:templatename=“parse”> <xsl:paramname=“unrendered”/> … </xsl:template> <xsl:templatename=“parseTagContent”> <xsl:paramname=“tag”/> <xsl:paramname=“tag-content”/> … </xsl:template> 7 Templates 382 Lines 15,167 Characters [07truncate-wordcount.xsl] Amy Liu & Brett Goodwin
EXSLT • Although XSLT lacks features like loops and mutable variables, it is considered Turing-complete, meaning that given sufficient memory, XSLT can perform any calculation that can be performed by a modern computer program. However, this theoretical ability is often impractical. • EXSLT is a community initiative to provide extensions to XSLT 1.0 and to partition them into functional groups that can be implemented on an á la carte basis. The EXSLT effort is an open one; anyone who wishes to contribute may do so. http://www.exslt.org/ • Many of the functions in EXSLT are simply shortcuts to equivalent behaviors that can be achieved using XSLT templates. For these functions, the EXSLT authors have provided XSLT templates that may be imported into existing style sheets. This approach offers the most portability, as all XSLT 1.0-compliant processors are able to correctly interpret the template and provide the functionality. Amy Liu & Brett Goodwin
3rd Option:Truncate using str:tokenize() <xsl:variablename=“word-count” select=“37”/> <xsl:templatematch=“system-index-block”> <xsl:apply-templatesselect=“//system-page”> <xsl:sortorder=“descending” select=“start-date”/> </xsl:apply-templates> </xsl:template> <xsl:templatematch=“system-page”> <h3><xsl:value-ofselect=“title”/></h3> <p> <xsl:for-eachselect=“str:tokenize(string(page-xhtml))”> <xsl:iftest=“position() < $word-count”> <xsl:value-ofselect=“.”/><xsl:text> </xsl:text> </xsl:if> </xsl:for-each> <xsl:text>...</xsl:text> </p> <p><a href=“{path}” title=“More”>More...</a></p> </xsl:template> Be sure to specify the extension namespace URI & use the extension-element-prefix! <xsl:stylesheetversion=“1.0” xmlns:xsl=“http://www.w3.org/1999/XSL/Transform” xmlns:str=“http://exslt.org/strings” extension-element-prefixes=“str” > [08exslt-tokenizer.xsl] Amy Liu & Brett Goodwin
Problem #3:Formatting Date & Time… Example Scenario: Now that you have successfully truncated your blog posts, the next item to tackle is to format and display the date/time that is associated with each post. As you probably know, all date values within Cascade are represented in UNIX timestamp format (i.e., <start-date>1221165000000</start-date>). [04recent-blogs.xml] Amy Liu & Brett Goodwin
Problem #3:Formatting Date & Time… • If you were to attempt this calculation using only native XSLT 1.0, it will probably take about 304 lines or 10,345 characters. • The EXSLT Dates-and-Times functions don’t have anything readily available for use with UNIX timestamps. • Any other options? Amy Liu & Brett Goodwin
That’s right!Xalan Extensions • Xalan is the XSLT processor that Cascade Server utilizes. • For those situations where you would like to augment the functionality of XSLT with calls to a procedural language, Xalan-Java supports the creation and use of extension elements and extension functions. • The Xalan XSLT processor can invoke almost any method in almost any Java™ class in the classpath. Doing so can improve performance, provide features like trigonometric functions that aren't available in XSLT, perform file I/O, talk to databases and network servers, or implement algorithms that are easy to write in the Java language but hard to write in XSLT. • Typically, you'll resort to using Xalan extensions when you can't accomplish what you need using the existing XSLT or EXSL functions and need to write your own custom functions in Javascript or Java. Amy Liu & Brett Goodwin
Xalan Date Converter <p class=“date”> <xsl:value-ofselect=“date-converter:convertMonth(number(start-date))”/>  <xsl:value-ofselect=“date-converter:convertDate(number(start-date))”/>, <xsl:value-ofselect=“date-converter:convertYear(number(start-date))”/> </p> <h3><xsl:value-ofselect=“title”/></h3> <p><xsl:for-eachselect=“str:tokenize(string(page-xhtml))”> <xsl:iftest=“position() < $word-count”> <xsl:value-ofselect=“.”/> <xsl:text> </xsl:text> </xsl:if> </xsl:for-each> <xsl:text>...</xsl:text></p> <xalan:componentfunctions="convertDate" prefix="date-converter"> <xalan:scriptlang="javascript"> function convertMonth(date) { var months = new Array(13); months[0] = "January"; months[1] = "February"; months[2] = "March"; months[3] = "April"; months[4] = "May"; months[5] = "June"; months[6] = "July"; months[7] = "August"; months[8] = "September"; months[9] = "October"; months[10] = "November"; months[11] = "December"; var d = new Date(date); // Splits date into components var month = months[d.getMonth()]; return month; } convertDay(date) {…} convertDate(date) {…} convertYear(date) {…} convertTime(date) {…} </xalan:script> </xalan:component> [09xalan-convertdate.xsl] Amy Liu & Brett Goodwin
Velocity! The Non-XSLT Bonus • Velocity is a Java-based template engine that Cascade Server will support starting with version 5.7 • It can be used to generate web pages, SQL, PostScript and other output from templates • Velocity Template Language (VTL) should have a lower learning curve than XSLT for developers who are already familiar with traditional programming languages • Utilizing VTL Formats, in some cases, can simplify the transformation code within Cascade http://velocity.apache.org/engine/devel/user-guide.html Amy Liu & Brett Goodwin
Context Menu Comparison XSLT Format VTL Format <ul> #foreach($child in $contentRoot.children) <li> <a href=“$child.getChild(“path”).text”> $child.getChild(“name”).text </a> </li> #end </ul> <xsl:templatematch=“/”> <ul> <xsl:apply-templatesselect=“//system-page | //system-folder”/> </ul> </xsl:template> <xsl:templatematch=“system-page | system-folder”> <li> <a href=“{path}”> <xsl:value-ofselect=“name”/> </a> </li> </xsl:template> Amy Liu & Brett Goodwin