Wednesday, January 11, 2012

Designing a Generic Meta-Data Driven Transformation Template (Ektron Designing Content Delivery: Part 3)

In the previous Ektron Designing Content Delivery post (Designing Data Templates for Content Extraction with Ektron (JSon, XML) (Ektron Designing Content Delivery: Part 2)), I outlined the basics of creating a series of templates for data extraction.

While using Ektron content as data is useful (in particular SmartForm data), there is always a need to render transformed content (as Html, Text, Csv, or other formatted content). In this post, I will outline a method to create a simple Meta-Data driven Ektron template that can use used to transform your data for presentation.

What this is useful for:
  • SmartForm content that needs to be displayed as Html
  • SmartForm content that needs to be transformed (to other Xml, Html, Text, Csv, etc)
  • Any Ektron content that requires transformation before being rendered, and represents stand-alone content.
A high level overview of the rendering process:

Of note: I've also created an Ektron Widget control that follows the same pattern, so that I can render out this content as part of a page-builder page without any additional work by the end user. It pretty much works the same way with the template being a page-builder widget, and the end consumption being a Page-builder page.

Transformation Template:
System/Design Requirements:
1. Support Multiple Xsl/Xslt translations against the content set
2. When not configured properly then display a simple message back for the rendered content.
3. Support different separators/delimiters within the metadata in-case there is a conflict and it needs to be changed or updated.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="MetaDataTransformation.aspx.cs" Inherits="ContentManagement.Site.Shared.Template.Content.SmartForm.MetaDataTransformation" %>
<%@ Register Assembly="Ektron.Cms.Controls" Namespace="Ektron.Cms.Controls" TagPrefix="CMS" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "">

<html xmlns="">
<head id="Head1" runat="server">
    <form id="form1" runat="server">
        <CMS:ContentBlock ID="ContentBlock1" runat="server" />

using System;
using ContentManagement.Ektron.Content;
using ContentManagement.Ektron.Transformation.Xsl;
using ContentManagement.Site.Shared.Pages;
using MetaData = Ektron.Cms.API.Metadata;
using ContentManagement.Ektron.Transformation;

namespace ContentManagement.Site.Shared.Template.Content.SmartForm
    public partial class MetaDataTransformation : AbstractCmsPage
        protected void Page_Load(object sender, EventArgs e)
            this.ContentBlock1.SetDynamicParameterToIdAndFill(); //prep content block


            Response.ContentType = ContentManagement.Web.ContentTypeDefinition.Html;

            var id = this.ContentBlock1.EkItem.Id; //retrieve the id from the item

var metaData = this.ContentBlock1.GetMetaData().GetItemByName("Transformation"); //Note: This should be content/error content from Ektron. Action badRender = () => Response.Write("Oppps. It looks like this content isn't ready yet. Try back again soon."); if (metaData == null) //meta data not located on this item, so we do not want it to render. badRender(); else { var data = new MetaData(); var metaDataType = data.GetMetadataType(long.Parse(metaData.ID)); var xsltTransformationFromMetaData = this.ContentBlock1.GetMetaData().GetItemByName("Transformation").Value.ToString().Split(new string[1] { metaDataType.Separater }, StringSplitOptions.RemoveEmptyEntries); var transform = XslTransformFactory.Get(); var input = this.ContentBlock1.EkItem.Html; if (xsltTransformationFromMetaData.Length <= 0) //no content, write out a simple error message. badRender(); else if (xsltTransformationFromMetaData.Length == 1) { //apply single transformation, and output directly to response stream transform.Transform( new XmlStringInput(input) , new XslFileInput(TransformationPath.MapPathAndValidate(this, xsltTransformationFromMetaData[0])) , Response.OutputStream , Response.Output.Encoding); } else { //apply multiple translations xsltTransformationFromMetaData.ForEach(trns => input = transform.Transform(new XmlStringInput(input), new XslFileInput(TransformationPath.MapPathAndValidate(this, trns)))); } } Response.End(); } } }

The steps for setup and configuration are pretty simple:
Ektron Configuration
  • Creation of the Meta-Data within Ektron
  • Sample Metadata Transformation within Ektron 8.0.2
  • Apply the Metadata to the Content Folder(s)
  • Metadata applied to the content folder
  • Add Meta-Data Driven Transformation Template to your content
Content Configuration
  • Add the MetaData to the Content
  • Meta Data Transformation on Content (Note: This has two transformations)
  • Set the Template for the Content to the Transformation Template
  • Add the correct meta data transformation template.

If your planning on using this with any type of volume you will want to cache the output of the transformation.

It's important to note that I am not referring to adding a custom style sheet to an Ektron web control (which you can do, and is extremely flexible) in particular this template will retrieve Ektron content, apply transformations and then write the result of the transformation to the response output. The application (and usage) of this for consumption of Ektron content is quite different. If your developing pages within Ektron, and want to transform the output of the control, using Ektron's own transformation infrastructure is a much better option. Here, I am transforming, and then providing content via a push/pull to other sites for content presentation (and providing an option to present that content fully rendered).

Q & A
Q: How is this different than adding a Cms control to the page and selecting a transformation? 
A: At the end of the day, it's not all that different, but I wanted a way to make this process completely configuration driven so I can set up additional content at will without having to create a page or a template for each set of content. 

In my next posts
1. Designing a wrapper-API for consumption, caching and rendering of Ektron data.
2. Now look what we can do: Render Ektron client-side with data templates and JsRender (for smoking fast response times).
3. My Ektron page templates

Designing an Ektron Content Delivery and Provider Mechanism (Part 1)
Designing Data Templates for Content Extraction with Ektron (JSon, XML) (Ektron Designing Content Delivery: Part 2)
Guest Blogger-Cameron Jordan: No More XSLT?!


Personable Pet Care said...

nice blog and thanks for posting this data..

Brielle Franklin said...

This is great information. I have been looking for information on data transformation for my company. I have not come across a blog that has been so detailed as this one. Thanks so much for this post.