Archive

Archive for the ‘XSL’ Category

AJAX JavaScript Control (2012 Update)

May 18, 2012 1 comment

AJAX Control lets you quickly embed AJAX controls using text, XML and XSLT in a variety of ways to your web pages. Read more…

IE7 Conditional Comments and XSL

March 18, 2008 Leave a comment

About conditional comments

Conditional comments in Internet Explorer 7 are a way to ensure only IE or non-IE browsers parse certain parts of a page. This is mostly used to include CSS compatibility hacks by way of a <link> element in the page header, but they can in fact wrap any amount of HTML anywhere in the document. Read more…

XSL Date & Time Library

January 26, 2008 Leave a comment

XSL Date & Time Library is an XSL stylesheet which provides various date and time functions for use within your own XSL stylesheets. Read more…

How to tidy up badly formatted XML with an XSL stylesheet

January 21, 2008 1 comment

How do you turn this:

<broadcastScheduler><!-- ================================================================ --><!--
CURRENT SHOWS --><!-- ================================================================ --><recurr
ingBroadcast href="show-varee-season-2" indexStart="26" recurFrequency="14"><firstAirDate channel
="d2" date="2007-09-21T22:00:00-06:00" dstRules="us" automaticStartup="false"/><firstAirDate chan
nel="d1" date="2007-10-05T22:00:00+00:00" dstRules="eu" automaticStartup="true"/></recurringBroad
cast><recurringBroadcast href="show-dan-ascherl-season-1" indexStart="6" recurFrequency="1md"><fi
rstAirDate channel="d1" date="2007-05-04T22:00:00+01:00" dstRules="eu" automaticStartup="true"/><
firstAirDate channel="d2" date="2007-05-04T22:00:00-05:00" dstRules="us" automaticStartup="true"/
><firstAirDate channel="d1" date="2007-05-18T22:00:00+01:00" dstRules="eu" automaticStartup="true
"/><firstAirDate channel="d2" date="2007-05-18T22:00:00-05:00" dstRules="us" automaticStartup="tr
ue"/></recurringBroadcast><recurringBroadcast href="show-bent-killer-season-1" indexStart="21" re
curFrequency="14"><firstAirDate channel="d1" date="2007-08-29T19:30:00+01:00" dstRules="eu" autom
aticStartup="true"/><firstAirDate channel="d2" date="2007-08-29T19:30:00-05:00" dstRules="us" aut
omaticStartup="true"/></recurringBroadcast><recurringBroadcast href="show-serge-season-1" indexSt
art="6" recurFrequency="7"><firstAirDate channel="d1" date="2007-05-04T22:00:00+02:00" dstRules="
eu" automaticStartup="true"/><firstAirDate channel="d2" date="2007-05-04T21:00:00-05:00" dstRules
="us" automaticStartup="true"/></recurringBroadcast><recurringBroadcast href="show-neil-bowles-se
ason-1" indexStart="15" recurFrequency="14"><firstAirDate channel="d1" date="2007-11-01T23:00:00+
01:00" dstRules="eu" automaticStartup="true"/><firstAirDate channel="d2" date="2007-11-01T23:00:0
0-05:00" dstRules="us" automaticStartup="true"/></recurringBroadcast>

into this:

<broadcastScheduler>
<!-- ================================================================ -->
<!-- CURRENT SHOWS -->
<!-- ================================================================ -->
  <recurringBroadcast href="show-varee-season-2" indexStart="26" recurFrequency="14">
    <firstAirDate channel="d2" date="2007-09-21T22:00:00-06:00" dstRules="us" automaticStartup="false"/>
    <firstAirDate channel="d1" date="2007-10-05T22:00:00+00:00" dstRules="eu" automaticStartup="true"/>
  </recurringBroadcast>
  <recurringBroadcast href="show-dan-ascherl-season-1" indexStart="6" recurFrequency="1md">
    <firstAirDate channel="d1" date="2007-05-04T22:00:00+01:00" dstRules="eu" automaticStartup="true"/>
    <firstAirDate channel="d2" date="2007-05-04T22:00:00-05:00" dstRules="us" automaticStartup="true"/>
    <firstAirDate channel="d1" date="2007-05-18T22:00:00+01:00" dstRules="eu" automaticStartup="true"/>
    <firstAirDate channel="d2" date="2007-05-18T22:00:00-05:00" dstRules="us" automaticStartup="true"/>
  </recurringBroadcast>
  <recurringBroadcast href="show-bent-killer-season-1" indexStart="21" recurFrequency="14">
    <firstAirDate channel="d1" date="2007-08-29T19:30:00+01:00" dstRules="eu" automaticStartup="true"/>
    <firstAirDate channel="d2" date="2007-08-29T19:30:00-05:00" dstRules="us" automaticStartup="true"/>
  </recurringBroadcast>
  <recurringBroadcast href="show-serge-season-1" indexStart="6" recurFrequency="7">
    <firstAirDate channel="d1" date="2007-05-04T22:00:00+02:00" dstRules="eu" automaticStartup="true"/>
    <firstAirDate channel="d2" date="2007-05-04T21:00:00-05:00" dstRules="us" automaticStartup="true"/>
  </recurringBroadcast>
  <recurringBroadcast href="show-neil-bowles-season-1" indexStart="15" recurFrequency="14">
    <firstAirDate channel="d1" date="2007-11-01T23:00:00+01:00" dstRules="eu" automaticStartup="true"/>
    <firstAirDate channel="d2" date="2007-11-01T23:00:00-05:00" dstRules="us" automaticStartup="true"/>
  </recurringBroadcast>

3,000 lines of the above was the horror I woke upto one day when PHP decided to stop formatting automated changes to our radio schedules properly. We need our schedules XML to be human-readable so I had to come up with a quick way to reformat it. Read more…

Categories: XSL Tags:

Unique key grouping with multiple input documents and nodesets in variables

September 8, 2006 Leave a comment

The problem

A common requirement in XSL transformations is to group unsorted data by a key unique to each group, and sort it for display. For example:

<?xml version="1.0"?>
<food>
  <item type="Fruit" name="Orange" />
  <item type="Vegetable" name="Cucumber" />
  <item type="Meat" name="Chicken" />
  <item type="Vegetable" name="Carrot" />
  <item type="Vegetable" name="Potato" />
  <item type="Meat" name="Pork" />
  <item type="Fruit" name="Banana" />
  <item type="Fruit" name="Apple" />
</food>

We may typically want to output an HTML table with each food type (Fruit, Meat, Vegetable) as a header with all the items in each food category as table rows/records, ie.

Fruit
Apple
Banana
Orange
Meat
Chicken
Pork
Vegetable
Carrot
Cucumber
Potato

When dealing with a single input document addressed directly (ie. not through a variable), this is a trivial problem for XSL, easily solvable using <xsl:key> and key().

This technique fails when you must group a node-set stored in a variable or in an external document referenced with document() because <xsl:key> does not allow you to use variables or document() in its attributes – it is only capable of indexing the main source document. Additionally, XPath axes we might use for testing uniqueness in a set (typically preceding-sibling:: in an <xsl:for-each> to see if we have found the first occurrence of a new group key) do not function on external documents referenced by document().

So how do we group with XSL variables or multiple input documents? Read more…

Categories: XSL Tags: , ,