Created
November 20, 2013 21:08
-
-
Save xymox12/7571057 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<xsl:stylesheet version="1.0" | |
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" | |
xmlns:ical="http://www.ietf.org/rfc/rfc2445.txt" | |
xmlns:itip="http://www.ietf.org/rfc/rfc2446.txt" | |
xmlns="http://www.ietf.org/rfc/rcf2445.txt"> | |
<!-- ======================================================================== --> | |
<!-- ics2xml.xsl XSL transformation of iCalendar .ics file to XML file --> | |
<!-- Tim Hare, November 2006 --> | |
<!-- This transformation may be freely used, attribution is appreciated --> | |
<!-- ======================================================================== --> | |
<!-- define output format --> | |
<xsl:output method="xml" media-type="xml/calendar" indent="yes" /> | |
<!-- --> | |
<!-- global parameters of use throughout the stylesheet --> | |
<!-- --> | |
<xsl:variable name="newline"><xsl:text> | |
</xsl:text></xsl:variable> | |
<xsl:variable name="linewrap"><xsl:text> | |
</xsl:text></xsl:variable> | |
<xsl:variable name="CR"> </xsl:variable> | |
<xsl:variable name="colon"><xsl:text>:</xsl:text></xsl:variable> | |
<xsl:variable name="semicolon"><xsl:value-of select="concat(';','')" /></xsl:variable> | |
<xsl:apply-templates select="*" /> | |
<xsl:template match="/"> | |
<xsl:element name="iCalendar_Stream"> | |
<xsl:call-template name="convert_ics"> | |
<!-- "parameter" is the entire input file --> | |
<xsl:with-param name="icaldata"> | |
<!-- --> | |
<!-- First we adjust the whitespace in the incoming document .ics --> | |
<!-- file. Can NOT use normalize-space() or document() because they --> | |
<!-- remove the the CR-LF sequence crucial to recognizing the end of --> | |
<!-- things in iCalendar --> | |
<!-- --> | |
<xsl:call-template name="space_adjust"> | |
<xsl:with-param name="icsinput"> | |
<xsl:value-of select="current()" /> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:element> | |
</xsl:template> | |
<!-- Process recursively. --> | |
<!-- Find Calendars and Components (BEGIN/END pairs) --> | |
<!-- and then process properties with parameters --> | |
<!-- try find BEGIN: then extract name and search for END:$name --> | |
<xsl:template name="convert_ics"> | |
<xsl:param name="icaldata" /> | |
<xsl:choose> | |
<xsl:when test="$icaldata = $newline"> | |
<!-- do nothing if it's only newline --> | |
</xsl:when> | |
<xsl:when test="starts-with($icaldata,'BEGIN:')"> | |
<xsl:variable name="element_name"> | |
<xsl:value-of select="substring-before(substring-after($icaldata,'BEGIN:'),$newline)" /> | |
</xsl:variable> | |
<xsl:choose> | |
<xsl:when test="substring-before($icaldata,concat('END:',$element_name))"> | |
<xsl:value-of select="$newline" /> | |
<xsl:element name="{concat($element_name,'')}"> | |
<xsl:call-template name="convert_ics"> | |
<xsl:with-param name="icaldata"> | |
<xsl:value-of select="substring-before(substring-after($icaldata,concat('BEGIN:',$element_name,$newline)),concat('END:',$element_name,$newline))" /> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:element> | |
</xsl:when> | |
<xsl:otherwise> | |
</xsl:otherwise> | |
</xsl:choose> | |
<xsl:choose> | |
<xsl:when test="substring-after($icaldata,concat('END:',$element_name,$newline))" > | |
<xsl:call-template name="convert_ics"> | |
<xsl:with-param name="icaldata"> | |
<xsl:value-of select="substring-after($icaldata,concat('END:',$element_name,$newline))" /> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:when> | |
<xsl:otherwise> | |
</xsl:otherwise> | |
</xsl:choose> | |
</xsl:when> | |
<xsl:otherwise> | |
<!-- It isn't a BEGIN/END pair, so it's a property --> | |
<!-- each property becomes an element, each parameter an attribute of it --> | |
<xsl:variable name="element_name"> | |
<xsl:choose> | |
<!-- if there's a semicolon, then the name is the string before the semicolon --> | |
<xsl:when test="contains(substring-before($icaldata,$colon),$semicolon)" > | |
<xsl:value-of select="substring-before($icaldata,$semicolon)" /> | |
</xsl:when> | |
<!-- otherwise the name is the string before the colon --> | |
<xsl:otherwise> | |
<xsl:value-of select="substring-before($icaldata,$colon)" /> | |
</xsl:otherwise> | |
</xsl:choose> | |
</xsl:variable> | |
<!-- --> | |
<!-- Now create the elements --> | |
<!-- --> | |
<xsl:value-of select="$newline" /> | |
<xsl:element name="{string($element_name)}" > | |
<!-- --> | |
<!-- If there is a semicolon, then we have property parameters which we --> | |
<!-- need to make into attributes of the element --> | |
<!-- --> | |
<xsl:if test="contains(substring-before($icaldata,$colon),$semicolon)" > | |
<xsl:call-template name="process_parameters"> | |
<xsl:with-param name="parameters"> | |
<!--- everything from the first semicolon to the colon are properties --> | |
<xsl:value-of select="substring-after(substring-before($icaldata,$colon),$semicolon)" /> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:if> | |
<!-- --> | |
<!-- contents of the element are everything after the colon --> | |
<!-- precede it with white space, to make it look better --> | |
<!-- --> | |
<xsl:value-of select="substring-before(substring-after($icaldata,$colon),$newline)" /> | |
</xsl:element> | |
<xsl:if test="substring-after($icaldata,$newline)"> | |
<xsl:call-template name="convert_ics"> | |
<xsl:with-param name="icaldata"> | |
<xsl:value-of select="substring-after($icaldata,$newline)" /> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:if> | |
</xsl:otherwise> | |
</xsl:choose> | |
</xsl:template> | |
<xsl:template name="process_parameters"> | |
<!--- recursively strip out parameters and make attributes of them --> | |
<xsl:param name="parameters" /> | |
<xsl:choose> | |
<!-- if more than one parameter present they are separated by semicolons --> | |
<xsl:when test="substring-before($parameters,$semicolon)"> | |
<xsl:attribute name="{substring-before(substring-before($parameters,$semicolon),'=')}"> | |
<xsl:value-of select="substring-after(substring-before($parameters,$semicolon),'=')" /> | |
</xsl:attribute> | |
<xsl:call-template name="process_parameters"> | |
<xsl:with-param name="parameters"> | |
<xsl:value-of select="substring-after($parameters,$semicolon)" /> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:when> | |
<xsl:otherwise> | |
<xsl:if test="contains($parameters,'=')"> | |
<xsl:attribute name="{substring-before($parameters,'=')}"> | |
<xsl:value-of select="substring-after($parameters,'=')" /> | |
</xsl:attribute> | |
</xsl:if> | |
</xsl:otherwise> | |
</xsl:choose> | |
</xsl:template> | |
<xsl:template name="space_adjust"> | |
<!-- --> | |
<!-- This template removes leading spaces, and line-wrap sequences from the input, returning a --> | |
<!-- variable which may still contain CR-LF sequences but not CR-LF-space --> | |
<!-- it is invoked once as the entire iCalendar input file is turned into a variable --> | |
<xsl:param name="icsinput" /> | |
<xsl:variable name="special_case"><xsl:value-of select="concat($newline,'BEGIN:')" /></xsl:variable> | |
<xsl:choose> | |
<xsl:when test="starts-with($icsinput,$special_case)"> <!-- Special case --> | |
<xsl:call-template name="space_adjust"> | |
<xsl:with-param name="icsinput"> | |
<xsl:value-of select="substring-after($icsinput,$newline)" /> <!-- strip leading NL --> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:when> | |
<!-- --> | |
<!-- To hold down recursion depth and iterations, test for different lengths of leading --> | |
<!-- spaces before recursively calling this routine --> | |
<xsl:when test="starts-with($icsinput,' ')"> <!-- five spaces --> | |
<xsl:call-template name="space_adjust"> | |
<xsl:with-param name="icsinput"> | |
<xsl:value-of select="substring-after($icsinput,' ')" /> <!-- strip five --> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:when> | |
<xsl:when test="starts-with($icsinput,' ')"> <!-- four spaces --> | |
<xsl:call-template name="space_adjust"> | |
<xsl:with-param name="icsinput"> | |
<xsl:value-of select="substring-after($icsinput,' ')" /> <!-- strip four --> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:when> | |
<xsl:when test="starts-with($icsinput,' ')"> <!-- three spaces --> | |
<xsl:call-template name="space_adjust"> | |
<xsl:with-param name="icsinput"> | |
<xsl:value-of select="substring-after($icsinput,' ')" /> <!-- strip three --> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:when> | |
<xsl:when test="starts-with($icsinput,' ')"> <!-- two spaces --> | |
<xsl:call-template name="space_adjust"> | |
<xsl:with-param name="icsinput"> | |
<xsl:value-of select="substring-after($icsinput,' ')" /> <!-- strip two --> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:when> | |
<xsl:when test="starts-with($icsinput,' ')"> <!-- one space --> | |
<xsl:call-template name="space_adjust"> | |
<xsl:with-param name="icsinput"> | |
<xsl:value-of select="substring-after($icsinput,' ')" /> <!-- strip one --> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:when> | |
<!-- --> | |
<!-- At this point all leading spaces should be gone, so we look for linewraps to remove --> | |
<!-- --> | |
<xsl:when test="substring-before($icsinput,$linewrap)"> | |
<xsl:call-template name="space_adjust"> | |
<xsl:with-param name="icsinput"> | |
<!-- replace the linewrap with a single space --> | |
<xsl:value-of select="concat(substring-before($icsinput,$linewrap),' ',substring-after($icsinput,$linewrap))" /> | |
</xsl:with-param> | |
</xsl:call-template> | |
</xsl:when> | |
<xsl:otherwise> | |
<xsl:value-of select="$icsinput" /> | |
</xsl:otherwise> | |
</xsl:choose> | |
</xsl:template> | |
</xsl:stylesheet> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment