BASICS

ADMINISTRATION

DEVELOPMENT

SUPER ADMIN

  LAST UPDATED
6/3/2013

Using XSL to Transform Content

Code snippets can be transformed to create pre-styled or pre-structured HTML widgets.

All websites make use of complex code structures, or “widgets,” and usually have very specific style formats. These aspects are usually built into the XSL templates, but often there is a need to have end-users easily be able to add and maintain these “widgets” in the middle of an editable region.

This tutorial provides examples of how to use XSL to transform simple HTML tables into the following fancy widgets: An introductory “Hero Unit,” a multi-column region, and a collapsible accordion widget. These XSL techniques can provide the tools to attack new and modern content styling that current websites employ. Twitter Bootstrap’s HTML and CSS structure are used as a base for the sample page templates and the code pieces. 

In the examples provided, specially crafted HTML tables serve as the editable tool for storing the complex widgets content. Storing these tables as OU Campus snippets allow end-users to procure these special tables for their pages. Users update the data in the table and save, and the XSL takes care of the rest.

Getting Started

The transforming content tutorial includes the use and modification of several files commonly used in OU Campus. These include the following file types: .pcf, .html, .css, .txt, .js, and .xsl. Some code snippets are provided in-context, but to work through tutorial requires modifying the various files within OU Campus. The files used in the tutorial are provided in a zip file:

XSL Transformations (zip)

The zip file can be downloaded to a local computer and the uploaded to OU Campus using Zip Import, which by default will decompress the files and keep the existing folder structure. The files can then be edited as necessary throughout the tutorial.

Provided are:

xsl-tranformations

  index.pcf

  sample.pcf

  task1.html

  task2.html

  task3.html

_resources

   css

      bootstrap.css

      bootstrap.min.css

      bootstrap-responsive.css

      bootstrap-responsive.min.css

   editor

      default.css

      styles.txt

   img

   js

      bootstrap.js

      bootstrap.min.js

      html5shiv.js

    snippets

      3-columns-table.txt

      accordion-table.txt

      hero-table.txt

    xsl

      default.xsl

      master.xsl

      ou-variables.xsl

Next Page

 

 

Understanding the Setup

The provided sample template files have been kept simplistic in order to focus on the key elements. However, understanding how these methods works in the example scenarios is key in applying it to more complicated templates. After uploading the zip package to OU Campus, examine the XSL and PCF using Source Editor to view the code. Start with the index.pcf and default.xsl. All examples are short as the longest only contains about 100 lines of code.

To start with the index.pcf should appear without CSS styling as follows:

Without Styling

Linking to a CSS File in the XSL

The included default.xsl includes a broken dependency manager link.Broken Link Example

Locate the code in the XSL that links to a stylesheet. For example:

<!-- Le styles -->
    <link href="{{f:nnnnn}}" rel="stylesheet" />

Use the File Path/File Browser tool to navigate to the bootstrap.css that was uploaded with the zip package:

/xsl-transformations/_resources/css/bootstrap.css

If Dependency Manager is enabled for the site, the correct link tag will be inserted.

Navigate back to Preview of the index.pcf and the view should now show the styling similar to the screen shot below:

Preview with Styling

About the PCF

The PCF file is an XML file that stores page-specific content in OU Campus. Edit the index.pcf using the Source Editor to view the code discussed below. Note that this PCF helps provides the structure that will result in the HTML output and the XSL will help populate the specifics.

The pcf-stylesheet declaration at the beginning of the file reveals two important pieces of information regarding the file — the XSL source that is used to transform the page and the pages final extension. Here is an example of that particular line:

<?pcf-stylesheet path="/xsl-transformations/_resources/xsl/default.xsl" extension="html"?>

path: The path attribute defines the path and file name of the XSL file to be used. In the above example, it is default.xsl. Adding the link to the correct CSS file in the XSL affected the PCF that is using the XSL in that it now has the styling defined in the CSS file; for example, bootstrap.css.

extension: The extension attribute defines the extension for the resultant output of the transformation. In the above example, it is an HTML extension.

The other important area to look at is the node (or tag) structure that leads up to the editable region. The first node (also known as the root node) is <document>. Rules state that an XML file can have only a single root node. Once inside the root node, an XML document can have any number of nodes desired.

This PCF also includes a head node for content that would typically be placed in the header of an HTML. For example, after publish this index.pcf includes metadata, the title, and the link to the CSS as shown below:

Head Code

In code view, it shows that there is a <config> node for Page Properties, and that OU Campus style tags are used to encapsulate certain nodes.

<!-- ouc:properties -->
<title>Using XSL to Transform Content</title>
<!-- /ouc:properties -->

For more information about page tagging syntax, styles, examples, and specifics in OU Campus, see:

Page Tagging

For this particular tutorial, the next important node is called <content>. The naming convention for nodes in a document depends on various factors; ideally the names should help developers easily navigate through a document. In this particular file, there is only one editable region and it is located inside the node called <main>.

The following example is just the <main> node from the index.pcf provided in the zip package. Note that within the start and end tags of the <main> node is the OU Campus transitional style tag for an editable region:

Syntax Example

<!-- ouc:div label="MainContent" group="Everyone" button="700" break="break" --><!-- /ouc:div -->

 In-Context Example 

<main>
<!-- ouc:div label="MainContent" group="Everyone" button="700" break="break" -->
<!-- ouc:editor csspath="/xsl-transformations/_resources/editor/default.css" cssmenu="/xsl-transformations/_resources/editor/styles.txt" width="1050"/ -->
<h2>Using XSL to Transform Content</h2>
<p>Text goes here...</p>
<table class="ou-hero-unit transform" style="width: 100%;">
<caption>Hero Unit Table</caption>
<tbody>
<tr><th>Title</th>
<td>
<h3>Batman</h3>
</td>
</tr>
<tr><th>Description</th>
<td>
<p>Description Text</p>
</td>
</tr>
<tr><th>Button</th>
<td><a href="#">Read More about this</a></td>
</tr>
</tbody>
</table>
<!-- /ouc:div -->
</main>

Editable regions in OU Campus are controlled by ouc:div tags. These div tags are denoted by a set of opening and closing div comment tags. The label attribute value needs to be unique per div tag. In the above example, the label attribute and value are:

label="MainContent"

The other attributes allow additional behaviors, including defining the access group as everyone, defining a button for the editable region and adding a break after the editing button.

The ouc:editor tag controls how end-users are able to edit the region. The attributes of the editor tag above, csspath and cssmenu, provide the locations for styling the WYSIWYG Editor. Learn more about using these attributes:

Third Level Tagging (aka In-Context Editing)

About the XSLs

XSL (eXtensible Stylesheet Language) is a templating language used to transform, translate, or render XML documents into a more readable format. In this case, the XSL transforms the PCF contents into an HTML output file.

View the default.xsl file. Within the prologue the ou-variables.xsl is imported:

<xsl:import href="ou-variables.xsl" />

While the “default.xsl” defines the document layout, the “ou-variables.xsl” defines necessary variables and parameters for transformation.

A Few Good Elements

Default.xsl exemplifies the use of XSL elements as well as transforming content.

xsl:value-of

Within the head of the default.xsl, the title of the output file is defined by using both an xsl:value-of element and with text.

<title>
<xsl:value-of select="title" /> | OmniUpdate User Training Conference 2013</title>

The xsl:value-of uses the select attribute to create a text string from the value of the attribute as defined in the PCF, which is Using XSL to Transform Content.

<title>Using XSL to Transform Content</title>
Browsers should show the title of an HTML file in the browser tab.

Title

xsl:copy-of

The default.xsl also exemplifies the use of the xsl:copy-of element.

<xsl:copy-of select="metadata/meta" />

The use of xsl:copy-of can be compared with xsl:value-of in this context and by reviewing the resultant output. Whereas value-of used the select attribute to just pull-in the value of the attribute and create a string of text with it, copy-of pulls in both the content and the structure as specified by the select attribute. In this example, the XPath defined by the select attribute includes metadata/meta. The  copy-of command gets the whole node set from the defined location.

In the PCF, the structure and content can be seen:

<metadata>
<!-- ouc:properties -->
<meta name="Description" content="Using XSL to Transform Content" />
<meta name="Keywords" content="XSL transformations" />
<!-- /ouc:properties -->
</metadata>

The metadata in the HTML output includes keywords and description meta tags with the defined content.

xsl:template

The opening template match (located at about line 19) defines the start of the output document.

<!-- START DOCUMENT -->
<xsl:template match="/document">

The HTML code (around line 71) includes a content region that resides inside a div node with a class of span9.

Here is that portion of the code:

<div class="span9">
<!-- GET CONTENT FROM <main> NODE -->
<xsl:apply-templates select="content/main/node()" />
</div><!--/span-->

The path found in the select attribute defines the XPath to the content region in the PCF document.

Content Node in the PCF

Since this template’s match attribute targets the root node, in this case the <document> node, the opening slash in the XPath is not required. For more information about XPath:

Introduction to XPath

Using Apply-Templates

The content to be transformed, the table snippet, needs in the middle of the content region, as the XSL will parse through every single item in the content area so that it can be singled out.

In order to get all the content to display, there must be a template match for every single item that could be inside the content region. Below is a single xsl:template element that uses the match attribute to match every item:

<!-- RECURSIVE TEMPLATE MATCH -->
      <xsl:template match="element()| attribute()|text()| comment()" >
            <xsl:copy>
                  <xsl:apply-templates select="attribute()|node()" />
            </xsl:copy>
      </xsl:template>

This recursive template uses generic XPath definitions to match all the types of nodes that could be found in the editable region. In this case element, attribute, text, and comment nodes. From there, it makes a shallow copy using the xsl:copy element, which outputs the current item. On that item, it then uses apply-templates for everything found inside the current item, including its attributes.

Essentially, this creates a soft version of the original copy-of command. What makes it soft is that it matches all elements and items using generic identifiers, and so template matches that use a more specific identifier take priority.

For example, this template <xsl:template match="p" > specifically targets paragraph tags, and therefore catches all paragraph tags instead of the generic template defined above. This method creates templates that match specific tables that are defined with special classes for identification.

 

Previous PageNext Page

  

Hero Unit: Using Template Matches

The goal of the exercise is to use the XSL to transform the data in the table snippet. The snippet provided, hero-table.txt file (xsl-transformations/_resources/snippets/hero-table.txt), uses two classes to define the table: ou-hero-unit and transform. It includes a caption and three rows with headers. The table will be dropped into the PCF and the XSL stylesheet is used to manipulate the data. The final styling of the content will be similar to the screen shot below in that there is a gray-blue box background with a bolded title (Title), a paragraph of text (Description), and a button with a link (Read More). 
 
Task #1 Goal - Intro (Hero Unit)

Edit the PCF

1. Insert the table snippet into the editable region in the index.pcf. The table snippet found in the provided hero-table.txt file (xsl-transformations/_resources/snippets/hero-table.txt) and is also provided below. 

2. Customize the content within the three data cells to ensure successfully viewing of the content later. The data can be edited as follows:

<th>Title<th>: Change the data cell contents <td></td> for the first row should include the name of the hero. Note the h3.
<th>Description</th>: The data cell <td></td> for the second row should include the description of the hero. Notice that there's a p within the td.

<th>Button</th>: The data cell for the third row should include the button label. Notice that it is a link.

<table class="ou-hero-unit transform" style="width: 100%;">
<caption>Hero Unit Table</caption><tbody>
<tr><th>Title</th><td><h3>Flash</h3></td></tr>
<tr><th>Description</th><td><p>The Fastest Man Alive</p></td></tr>
<tr><th>Button</th><td><a href="#">See Flash Run</a></td></tr>
</tbody>
</table><br />

Edit the XSL

Locate the Hero Unit template match in the default.xsl under the Special Template Matches comment:

<!-- Hero Unit -->
<xsl:template match="table[contains(@class, 'ou-hero-unit')]">
<!-- Hero Unit Code Goes Here ... -->
</xsl:template>

This xsl:template match specifically matches a table with a class attribute that has a value of ou-hero-unit. In this case, the table snippet that was added to the PCF included that class.

1. Replace the comment <!-- Hero Unit Code Goes Here ... --> with the following code:

<div class="hero-unit">
      <h3>Title</h3>
      <p>Description</p>
      <p><a href="#" class="btn btn-primary btn-large">Read More</a></p>
</div>

The three HTML elements correspond to the data cells within each step of the provided snippet table. The next step is to replace the placeholder text for the table cells with XPath expressions. The following examples of XSL and XPath logic show different syntax for traversing the document tree using XPath expressions.

2. Replace the Title content with the content from the table snippet as shown below:

<div class="hero-unit">
      <h3><xsl:value-of select="./tbody/tr[1]/td" /></h3>
      <p>Description</p>                                   
      <p><a href="#" class="btn btn-primary btn-large">Read More</a></p>
</div>

The text from the cell from the first row will be used. Literally, selects the current node then the first table row under table body and uses the value of the td to create the string.

3. Replace the Description content with the content in the table snippet from the second row as shown below:
<div class="hero-unit">
      <h3><xsl:value-of select="./tbody/tr[1]/td" /></h3>
      <xsl:copy-of select="./tbody/tr[2]/td/node()" />
      <p><a href="#" class="btn btn-primary btn-large">Read More</a></p>
</div>

The XPath expression in this case selects the current node, then the second row from the table body, then matches any node of the td.

4. Replace the link text with the link text from the table. 

<div class="hero-unit">
      <h3><xsl:value-of select="./tbody/tr[1]/td" /></h3>
      <xsl:apply-templates select="./tbody/tr[2]/td/node()" />
      <p><a href="#" class="btn btn-primary btn-large"><xsl:value-of select="./tbody/tr[3]/td//a" /></a></p>
</div>

This XPath expression uses the current node, then the third table row, then all a elements that are descendants of the td element and uses the value to create the string.

5. Also for the third row table cell, replace the href placeholder # with the expression shown below. 

<p>
<a href="{./tbody/tr[3]/td//a/@href}" class="btn btn-primary btn-large"><xsl:value-of select="./tbody/tr[3]/td//a" /></a>
</p>

This is similar to the previous expression except that instead of selecting all a descendants of the td only those a nodes with an href attribute are used to provide the string value.

With the changes made and the table data customized, the styling for the page should look similar to the following:

Hero unit populated with text.

 

The content contributor can edit the text of the table using the WYSIWYG Editor.

Hero table WYSIWYG View 

Complete XSL Code Snippet

<!-- Hero Unit -->
<xsl:template match="table[contains(@class, 'ou-hero-unit')]">
<div class="hero-unit">
      <!-- Title -->
      <h2><xsl:value-of select="./tbody/tr[1]/td" /></h2>

      <!-- Description -->
      <xsl:apply-templates select="./tbody/tr[2]/td/node()" />

      <!-- Button -->
      <p>
      <a href="{./tbody/tr[3]/td[1]//a/@href}" class="btn btn-primary btn-large">
      <xsl:value-of select="./tbody/tr[3]/td//a" />
      </a>
      </p>
</div>
</xsl:template>

Troubleshooting

Do not be afraid of the bomb! Error messages may seem complicated and cryptic at first glance; however, error message dialogs may indicate an error as simple as a missing end tag or an undefined character entity as each error message below was caused by, respectively. Highlighting in the Source Editor is designed to help identify syntax errors of the selected language.

The following error message occurred as there was an ampersand included in the PCF. 

Error Message Character Entity

The following error message, while verbose, precisely indicates the error. The last line indicates that there was a missing closing tag: </xsl:template>. It had been inadvertently deleted during editing.

Error Message with No Closing Tag

 

 

Previous PageNext Page

 

 

Transforming a Table into Three Column Content

The goal of this exercise is to transform content provided form of a table snippet in a PCF by using template:match in the XSL. The styling and transformation creates a three-column area of content by using the table. The steps and provided content are similar to the Hero Unit tutorial. The xsl:template element is used to match a table that contains a specific class.

Example of Final Styling 

Content Column Widget example

 

XSL Template Match Example

<!-- Columns Layout --
<xsl:template match="table[contains(@class, 'ou-columns')]">
      <!-- Columns Code Goes Here -->
</xsl:template>

Editing the PCF

1. Drop the following table snippet into an editable region. It is also provided in the zip package: xsl-transformations/_resources/snippets /3-columns-table.txt.

<table class="ou-columns transform" style="width: 100%;">
   <caption>3 Column Layout Table</caption>
   <tbody>
      <tr>
        <td class="span4" style="vertical-align:text-top; width: 33%;">
            <h3>Left Column</h3>
            <p>Content</p>
        </td>
        <td class="span4" style="vertical-align:text-top; width: 33%;">
            <h3>Middle Column</h3>
            <p>Content</p>
        </td>
        <td class="span4" style="vertical-align:text-top; width: 33%;">
            <h3>Right Column</h3>
            <p>Content</p>
        </td>
     </tr>
   </tbody>
</table>
<br />


2. Customize the content by replacing the word "Content" with text.

Editing the XSL

1. In the default.xsl, add the following HTML code into the pre-defined template match region, which is identified with the <!-- Columns Layout --> comment.

<div class="row-fluid">
<div class="span4">
<h3>Left Column</h3>
    <p>Content</p>      
</div>
  <div class="span4">
    <h3>Middle Column</h3>
    <p>Content</p>
  </div>
<div class="span4">
    <h3>Right Column</h3>
    <p>Content</p>
  </div>
</div>

 

2. Use the following XSL and XPath logic, which will replace each column’s content with the content from the table snippet.

<div class="row-fluid">
      <div class="span4">
            <xsl:apply-templates select="./tbody/tr[1]/td[1]/node()" />
      </div>
      <div class="span4">
            <xsl:apply-templates select="./tbody/tr[1]/td[2]/node()" />
      </div>
      <div class="span4">
            <xsl:apply-templates select="./tbody/tr[1]/td[3]/node()" />
      </div>
</div>

Note how each of these div columns are nearly identical, except that the cell number grows by one.

Variations

The template can be made more dynamic by having it create a new column for each cell in the row. This involves using the for-each element to select every td in the first row and then apply-templates is used to select all nodes within.

<div class="row-fluid">
      <xsl:for-each select="./tbody/tr[1]/td">
<div class="span4">
            <xsl:apply-templates select="./node()" />
         </div>
      </xsl:for-each>
</div>

The  table snippet column layout uses the class identifier that matches the CSS width settings:

<td class="span4" style="vertical-align:text-top; width: 33%;">

This particular class, span4, follows Bootstrap’s grid system and creates a column with a particular width (300px). Any different number of table snippets can be created that utilize a different class. Included is inline styling for the cell to behave more like a column instead of a table cell.

The XSL has specified a class: <div class="span4">, but instead the class can be acquired from the table cell. Update the XSL template match to acquire the class from the table cell by replacing the specific class with the syntax shown below.

<div class="row-fluid">
      <xsl:for-each select="./tbody/tr[1]/td">
<div class="{./@class}">
            <xsl:apply-templates select="./node()" />
      </div>
      </xsl:for-each>
</div>

Complete Dynamic XSL Example

<!-- Columns Layout -->
<xsl:template match="table[contains(@class, 'ou-columns')]">
      <div class="row-fluid">
            <xsl:for-each select="./td">
                  <div class="{./@class}">
                        <xsl:apply-templates select="./node()" />
                  </div><!--/span-->
            </xsl:for-each>  
      </div><!--/row-->
</xsl:template>

Advanced Solution

For a grid-like layout, add an extra for-each that allows the template to handle multiple rows:

<!-- Columns Layout -->
<xsl:template match="table[contains(@class, 'ou-columns')]">
      <xsl:for-each select="./tbody/tr">
            <div class="row-fluid">
                  <xsl:for-each select="./td">
                        <div class="{./@class}">
                              <xsl:apply-templates select="./node()" />
                        </div><!--/span-->
                  </xsl:for-each>  
            </div><!--/row-->
      </xsl:for-each>
</xsl:template>

 

Previous PageNext Page

 

 

Transforming a Table into an Accordion Widget 

The goal of this exercise is to transform content provided form of a table snippet in a PCF by using template:match in the XSL. The styling and transformation creates an accordion widget. The steps and provided content are similar to the Hero Unit tutorial. The xsl:template element is used to match a table that contains a specific class.

Example of Final Styling 

Accordion Widget Example 

XSL Template Match

<!-- Accordion Widget -->
<xsl:template match="table[contains(@class, 'ou-accordion')]">
      <!-- Accordion Code Goes Here -->
</xsl:template>

Editing the PCF

  1. Drop the table snippet inside the editable region
  2. Customize the content to ensure the successful viewing of content later.

Table Snippet

<h3>Accordion Widget</h3>
<table class="ou-accordion transform" style="width: 100%;">
<caption>Accordion Widget Table</caption>
<thead>
<tr>
<th width="30%">Teaser</th>
<th>Content</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<h5>Interesting Topic</h5>
</td>
<td>
<p>Interesting Content</p>
<p>Second Paragraph</p>
</td>
</tr>
<tr>
<td>
<h5>Another Topic</h5>
</td>
<td>
<p>Another content area.</p>
<ul><li>List Item</li>
<li>Another Item</li>
</ul>
</td>
</tr>
</tbody>
</table>
<br />

  

Editing the XSL

  1. In the default.xsl, locate the xsl:template for the accordion widget.
<!-- Accordion Widget -->
<xsl:template match="table[contains(@class, 'ou-accordion')]">
      <!-- Accordion Code Goes Here -->
</xsl:template>

2. Add the following HTML code into after the commnet: <!-- Accordion Code Goes Here ... -->.

<div class="accordion" id="accordion">
  <div class="accordion-group">
       <div class="accordion-heading">
          <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse-1">
          Interesting Topic #1
          </a>
        </div>
        <div id="collapse-1" class="accordion-body collapse in">
       <div class="accordion-inner">
           <p>Content #1</p>
          </div>
        </div>
   </div>
   <div class="accordion-group">
       <div class="accordion-heading">
          <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse-2">
           Interesting Topic #2
          </a>
       </div>
       <div id="collapse-2" class="accordion-body collapse">
          <div class="accordion-inner">
             <p>Content #2</p>
          </div>
       </div>
  </div>
</div>

 

3. Using the following XSL and XPath logic, replace the first grouping’s content (i.e., "Interesting Topic #1" and "Content #1") with the content from the table snippet’s first content row.

<div class="accordion" id="accordion">
      <div class="accordion-group">
            <div class="accordion-heading">
                  <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse-1">
                        <xsl:value-of select="./tbody/tr[1]/td[1]" />
                  </a>
            </div>
            <div id="collapse-1" class="accordion-body collapse">
                  <div class="accordion-inner">
                       <xsl:copy-of select="./tbody/tr[1]/td[2]/node()" />
                  </div>
            </div>
      </div>
<div class="accordion-group">
       <div class="accordion-heading">
          <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse-2">
           Interesting Topic #2
          </a>
       </div>
       <div id="collapse-2" class="accordion-body collapse">
          <div class="accordion-inner">
             <p>Content #2</p>
          </div>
       </div>
   </div>
</div>

 

4. The second group can be edited in a similar fashion by adding the appropriate copy-of and select to copy the next row and its table cells, since the first grouping is almost identical to the rest of the accordion items. However, like the previous three-column example, for-each and apply-templates elements can be used instead rather than defining each row and table cell. 

For each according group, the row is selected and then the cells with a numerical predicator.

<div class="accordion" id="accordion">
      <xsl:for-each select="./tbody/tr">
<div class="accordion-group">
            <div class="accordion-heading">
                  <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse-1">
                        <xsl:value-of select="./td[1]" />
                  </a>
            </div>
            <div id="collapse-1" class="accordion-body collapse">
                  <div class="accordion-inner">
                        <xsl:copy-of select="./td[2]/node()" />
                  </div>
            </div>
      </div>
      </xsl:for-each>
</div>

 

5. Finally, make the accordion groupings match up to their links, respectively.

<div class="accordion-group">
      <div class="accordion-heading">
            <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse-{position()}">
                  <xsl:value-of select="./td[1]" />
            </a>
      </div>
      <div id="collapse-{position()}" class="accordion-body collapse">
            <div class="accordion-inner">
                  <xsl:copy-of select="./td[2]/node()" />
            </div>
      </div>
</div>

Basic Solution

<!-- Accordion Widget -->
<xsl:template match="table[contains(@class, 'ou-accordion')]">
<div class="accordion" id="accordion">
      <xsl:for-each select="./tbody/tr">
<div class="accordion-group">
            <div class="accordion-heading">
                  <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse-{position()}">
                        <xsl:value-of select="./td[1]" />
                  </a>
            </div>
            <div id="collapse-{position()}" class="accordion-body collapse">
                  <div class="accordion-inner">
                        <xsl:copy-of select="./td[2]/node()" />
                  </div>
            </div>
      </div>
      </xsl:for-each>
</div>
</xsl:template>

Variations

To make it so that more than one accordion can work on a single page, use a dynamically created ID variable and add it to the id attribute fields.

To expand the first group in the accordion by default, add the in class to the first accordion element.

<!-- Accordion Widget -->
<xsl:template match="table[contains(@class, 'ou-accordion')]">
      <xsl:variable name="id" select="position()" />       
      <div class="accordion" id="accordion{$id}">    
            <xsl:for-each select="./tbody/tr">
                  <div class="accordion-group">
                        <div class="accordion-heading">
                              <a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion{$id}" href="#collapse-{$id}-{position()}">
                                    <xsl:value-of select="td[1]" />
                              </a>
                        </div>
                        <div id="collapse-{$id}-{position()}" class="accordion-body collapse {if (position()=1) then 'in' else ''}">
                              <div class="accordion-inner">
                                    <xsl:apply-templates select="td[2]/node()" />
                              </div>
                        </div>
                  </div><!--/accordion-group-->
            </xsl:for-each>
      </div><!--/accordion -->
</xsl:template>

 

Previous Page

 


Was this page helpful?

Additional Comments:


(Include your email address if you would like a reply)