Showing posts with label xslt. Show all posts
Showing posts with label xslt. Show all posts

Thursday, April 10, 2008

Macro for HTML encoding fields in templates

In Umbraco when you try to add a field to your template you can UrlEncode it like this :
<?UMBRACO_GETITEM field="MyField" urlEncode="true" />

But you can't do this :
<?UMBRACO_GETITEM field="MyField"  htmlEncode="true" />

I read in this forum thread that a fix for this has been submitted to codeplex but untill it's released I have made a macro to work around this.

First create a XSLT file and call it HTMLEncode and check the box "Create macro"

Then paste the following code in to your macro :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:Stylesheet [ &lt;!ENTITY nbsp "&#x00A0;"> ]>
<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:msxml="urn:schemas-microsoft-com:xslt"
    xmlns:umbraco.library="urn:umbraco.library"
    exclude-result-prefixes="msxml umbraco.library">


<xsl:output method="xml" omit-xml-declaration="yes"/>

<xsl:param name="currentPage"/>

<xsl:param name="field" select="/macro/field" />

<xsl:template match="/">

<!-- start writing XSLT -->
<xsl:if test="$field">
    <xsl:value-of select="$currentPage/data[@alias=$field]"/>
</xsl:if>
</xsl:template>

</xsl:stylesheet>

Then go to your macro and add a parameter called field of the type propertyTypePicker

In your templates you can now use this macro to htmlencode fields.

I hope you can use it.

Next blog will be about importing node with the webservices API.

Thursday, March 6, 2008

Transforming feeds...one XSLT to rule them all

For a client at my work I needed to built a feed reading module in to their CMS. I created the following XSLT to transform the feeds to the desired HTML. This XSLT can be used for Atom 0.3, Atom 1.0, RSS 0.90, RSS 0.91, RSS 0.92, RSS 1.0 and RSS 2.0.

With some minor tweaks this can be used in Umbraco as well. Here is an example of reading a atom feed in Umbraco.


Here is my XSLT.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:atom="http://www.w3.org/2005/Atom"
    xmlns:atom3="http://purl.org/atom/ns#"
    xmlns:rss="http://purl.org/rss/1.0/"
    xmlns:rss09="http://my.netscape.com/rdf/simple/0.9/"    
    exclude-result-prefixes="xsl rdf dc rss rss09 atom atom3"
>

<!--
=============================================================================
 XSLT to convert RSS and Atom feeds to desired html
=============================================================================
-->
<xsl:output method="html" omit-xml-declaration="yes" indent="yes"/>

<!--
=============================================================================
Input parameters for displaying maximum items from feed
=============================================================================
-->

<xsl:variable name="maxitems" select="10" />

<xsl:template match="/">
                
    <xsl:element name="ul">    
        <xsl:attribute name="class">rssfeed</xsl:attribute>        
        
        <!-- Atom 1.0 -->
        <xsl:apply-templates select="/atom:feed"/>
        <!-- Atom 0.3 -->
        <xsl:apply-templates select="/atom3:feed"/>
        <!-- RSS 0.91 , 0.92 , 2.0 -->
        <xsl:apply-templates select="rss/channel" />
        <!-- RSS 1.0 -->
        <xsl:if test="rdf:RDF/rss:item">
            <xsl:apply-templates select="rdf:RDF/rss:item[position() &lt; number($maxitems)+1]"/>
        </xsl:if>
        <!-- RSS 0.9 -->
        <xsl:if test="rdf:RDF/rss09:item">
            <xsl:apply-templates select="rdf:RDF/rss09:item[position() &lt; number($maxitems)+1]"/>
        </xsl:if>
        
    </xsl:element>

</xsl:template>


<!--
=============================================================================
 RSS 0.91,0.92,2.0
=============================================================================
-->
<xsl:template match="channel">        
    <xsl:apply-templates select="item[position() &lt; number($maxitems)+1]" />        
</xsl:template>

<xsl:template match="item">       
    <xsl:call-template name="drawlinks">
        <xsl:with-param name="item_link" select="link" />
        <xsl:with-param name="item_title" select="title" />
    </xsl:call-template>
</xsl:template>


<!--
=============================================================================
 RSS 1.0
=============================================================================
-->
<xsl:template match="rss:item">     
     <xsl:call-template name="drawlinks">
        <xsl:with-param name="item_link" select="rss:link" />
        <xsl:with-param name="item_title" select="rss:title" />
    </xsl:call-template>
</xsl:template>

<!--
=============================================================================
 RSS 0.90
=============================================================================
-->
<xsl:template match="rss09:item">    
    <xsl:call-template name="drawlinks">
        <xsl:with-param name="item_link" select="rss09:link" />
        <xsl:with-param name="item_title" select="rss09:title" />
    </xsl:call-template>
</xsl:template>

<!--
=============================================================================
Atom 1.0
=============================================================================
-->
<xsl:template match="/atom:feed">
    <xsl:apply-templates select="atom:entry[position() &lt; number($maxitems)+1]" />
</xsl:template>

<xsl:template match="atom:entry">
    <xsl:call-template name="drawlinks">
        <xsl:with-param name="item_link" select="atom:link/@href" />
        <xsl:with-param name="item_title" select="atom:title" />
    </xsl:call-template>
</xsl:template> 

<!--
=============================================================================
Atom 0.3
=============================================================================
--> 
<xsl:template match="/atom3:feed">    
    <xsl:apply-templates select="atom3:entry[position() &lt; number($maxitems)+1]" />    
</xsl:template>
 
<xsl:template match="atom3:entry">  
    <xsl:call-template name="drawlinks">
        <xsl:with-param name="item_link" select="atom3:link/@href" />
        <xsl:with-param name="item_title" select="atom3:title" />
    </xsl:call-template>
</xsl:template> 

<!--
=============================================================================
Template for making list items from feed items
=============================================================================
-->
<xsl:template name="drawlinks">
    <xsl:param name="item_link" />
    <xsl:param name="item_title" />
    <xsl:element name="li">        
        <xsl:element name="a">
            <xsl:attribute name="href"><xsl:value-of select="$item_link" /></xsl:attribute>
            <xsl:attribute name="target">_blank</xsl:attribute>
            <xsl:attribute name="title"><xsl:value-of select="$item_title" /></xsl:attribute>
            <xsl:value-of select="$item_title" />
        </xsl:element>    
    </xsl:element>
</xsl:template>
</xsl:stylesheet>

If you have issues with this, let me know.

Cheers,

Dave

Monday, January 28, 2008

Adding CSS or JavaScript to your mastertemplate based on documenttype

The way I normally work when making websites is to use several CSS-files and JavaScript-files. So most of the time I have a main.css and general.js file that is included in every page. But when I have pages that needed separate styling or clientside functionality I add for example a news.css and news.js. So I the visitor only has to download these file when needed.

In Umbraco there is no build-in function to append to the <head>-section of your mastertemplate from your childtemplate. To solve this I see several solutions :

  1. Build multiple mastertemplate
  2. Use a macro

Because solution 1 needs a lot of maintenance I decided to build a macro.

How does it work :

You insert this macro in to your mastertemplate. In the macro you decide based on the nodeTypeAlias attribute of the currentPage which CSS-file or JavaScript-file to add.

Here is the XSLT you need

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
  &amp;lt;!ENTITY nbsp "&#x00A0;">
]>
<xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxml="urn:schemas-microsoft-com:xslt"
    xmlns:umbraco.library="urn:umbraco.library"
    exclude-result-prefixes="msxml umbraco.library">


  <xsl:output method="xml" omit-xml-declaration="yes"/>

  <xsl:param name="currentPage"/>

  <xsl:template match="/">

    <xsl:choose>
      <xsl:when test="$currentPage/@nodeTypeAlias = 'News'">
        <xsl:call-template name="css">
          <xsl:with-param name="file">/css/news.css</xsl:with-param>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="$currentPage/@nodeTypeAlias = 'TextPage'">
        <xsl:call-template name="script">
          <xsl:with-param name="file">/scripts/textpage.js</xsl:with-param>
        </xsl:call-template>
      </xsl:when>
    </xsl:choose>

  </xsl:template>

  <xsl:template name="css">
    <xsl:param name="file" />
    <xsl:element name="link">
      <xsl:attribute name="rel">stylesheet</xsl:attribute>
      <xsl:attribute name="type">text/css</xsl:attribute>
      <xsl:attribute name="href">
        <xsl:value-of select="$file"/>
      </xsl:attribute>
    </xsl:element>
  </xsl:template>

  <xsl:template name="script">
    <xsl:param name="file" />
    <!-- to prevent that a self closing script tag is generated we use the xsl:text-->
    <xsl:text disable-output-escaping="yes"><![CDATA[<script language="javascript" type="text/javascript" src="]]></xsl:text>
    <xsl:value-of select="$file"/>
    <xsl:text disable-output-escaping="yes"><![CDATA["></script>]]></xsl:text>
  </xsl:template> 
</xsl:stylesheet>

If you think there is a way to improve this let me know !