Skip to content

Instantly share code, notes, and snippets.

@mro
Created January 20, 2010 15:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mro/281919 to your computer and use it in GitHub Desktop.
Save mro/281919 to your computer and use it in GitHub Desktop.
default namespace = "http://filmfestapp.com/schema/festival/v1"
namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
start =
## Flat Xml Schema for http://filmfestapp.com festival catalogues.
##
## This is a http://relaxng.org/ compact schema, to convert to RelaxNG regular or w3c-xsd use
## http://www.thaiopensource.com/relaxng/trang.html
##
## To validate use e.g. http://xmlsoft.org/xmllint.html
## $ xmllint --relaxng filmfest.flatv1.rng document.xml
element festival {
element creatorUrl {
xsd:anyURI { minLength = "1" }
},
geo?,
element homepage {
xsd:anyURI { minLength = "1" }
},
element iconUrl {
xsd:anyURI { minLength = "1" }
},
element section {
element movie {
element actor {
xsd:string { pattern = "\S(.*\S)?" }
}*,
element contact {
xsd:string { pattern = "\S(.*\S)?" }
}?,
element country {
xsd:string {
## subset of "ISO country code"
pattern = "[A-Z]{3}"
}
}+,
element synopsis { text },
element director {
xsd:string { pattern = "\S(.*\S)?" }
}+,
element distributor {
xsd:string { pattern = "\S(.*\S)?" }
}?,
element festivalUrl {
xsd:anyURI { minLength = "0" }
},
element footage {
xsd:string { pattern = "\S(.*\S)?" }
}?,
element iconUrl {
xsd:anyURI { minLength = "1" }
},
element imdbUrl {
xsd:anyURI { minLength = "1" }
},
element language {
xsd:string {
## A ISO 2-letter language code
pattern = "[a-z]{2}"
}
}*,
element otitle {
xsd:string { pattern = "\S(.*\S)?" }
}?,
element producer {
xsd:string { pattern = "\S(.*\S)?" }
}*,
element screening {
element minutes {
xsd:integer { minInclusive = "1" maxInclusive = "1440" }
},
element dtstart {
xsd:dateTime {
pattern =
"[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z"
}
},
uuid,
element venueref {
attribute idref { xsd:NCName }
}
}*,
element scriptwriter {
xsd:string { pattern = "\S(.*\S)?" }
}*,
element subtitle {
xsd:string { pattern = "\S(.*\S)?" }
}?,
title,
element trailerUrl {
xsd:anyURI {
## youtube only
pattern =
"http.+\.youtube\.com/(v/|watch\?v=)([A-Za-z0-9._%\-]+)"
}
}?,
element year {
xsd:integer { minInclusive = "1900" maxInclusive = "2100" }
}
}+,
title
}+,
element shortName {
xsd:string { pattern = "\S(.*\S)?" }
},
title,
uuid,
element venue {
attribute id { xsd:NCName },
element address {
element city {
xsd:string { pattern = "\S(.*\S)?" }
},
element country {
xsd:string { pattern = "\S(.*\S)?" }
},
element street {
xsd:string { pattern = "\S(.*\S)?" }
},
element zip {
xsd:string { pattern = "\S(.*\S)?" }
}
},
geo,
element phone {
xsd:string { pattern = "\S(.*\S)?" }
},
title
}+
}
geo =
element geo {
xsd:string {
## A geo location
pattern = "(-?[0-9]+\.[0-9]+)[,;](-?[0-9]+\.[0-9]+)"
}
}
uuid =
element uuid {
xsd:string {
## A UUID
pattern =
"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"
}
}
title =
element title {
xsd:string { pattern = "\S(.*\S)?" }
}
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:f="http://filmfestapp.com/schema/festival/v1"
exclude-result-prefixes="f">
<xsl:output method="xml" />
<xsl:output indent="yes" />
<xsl:template match="/">
<xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">]]></xsl:text>
<plist version="1.0">
<xsl:for-each select="f:festival">
<dict>
<key>schemaversion</key>
<integer>1</integer>
<xsl:for-each
select="f:geo | f:creatorUrl | f:iconUrl | f:homepage | f:uuid | f:shortName | f:title">
<key><xsl:value-of select="name(.)" /></key>
<string><xsl:value-of select="text()" /></string>
</xsl:for-each>
<key>sections</key>
<array>
<xsl:for-each select="f:section">
<dict>
<key>title</key>
<string><xsl:value-of select="f:title" /></string>
<key>movies</key>
<array>
<xsl:for-each select="f:movie">
<dict>
<xsl:for-each select="f:iconUrl | f:festivalUrl | f:trailerUrl | f:imdbUrl | f:title | f:footage | f:contact | f:distributor">
<key><xsl:value-of select="name(.)" /></key>
<string><xsl:value-of select="text()" /></string>
</xsl:for-each>
<xsl:for-each select="f:synopsis">
<key>description</key>
<string><xsl:value-of select="text()" /></string>
</xsl:for-each>
<xsl:for-each select="f:year">
<key><xsl:value-of select="name(.)" /></key>
<integer><xsl:value-of select="text()" /></integer>
</xsl:for-each>
<key>directors</key>
<array>
<xsl:for-each select="f:director">
<string><xsl:value-of select="text()" /></string>
</xsl:for-each>
</array>
<key>producers</key>
<array>
<xsl:for-each select="f:producer">
<string><xsl:value-of select="text()" /></string>
</xsl:for-each>
</array>
<key>actors</key>
<array>
<xsl:for-each select="f:actor">
<string><xsl:value-of select="text()" /></string>
</xsl:for-each>
</array>
<key>scriptwriters</key>
<array>
<xsl:for-each select="f:scriptwriter">
<string><xsl:value-of select="text()" /></string>
</xsl:for-each>
</array>
<key>countries</key>
<array>
<xsl:for-each select="f:country">
<string><xsl:value-of select="text()" /></string>
</xsl:for-each>
</array>
<key>languages</key>
<array>
<xsl:for-each select="f:language">
<string><xsl:value-of select="text()" /></string>
</xsl:for-each>
</array>
<key>subtitles</key>
<array>
<xsl:for-each select="f:subtitle">
<string><xsl:value-of select="text()" /></string>
</xsl:for-each>
</array>
<key>screenings</key>
<array>
<xsl:for-each select="f:screening">
<dict>
<key>duration</key>
<real><xsl:value-of select="f:minutes * 60" /></real>
<key>start</key>
<date><xsl:value-of select="f:dtstart" /></date>
<key>uuid</key>
<string><xsl:value-of select="f:uuid" /></string>
<key>venue</key>
<string><xsl:value-of select="f:venueref/@idref" /></string>
</dict>
</xsl:for-each>
</array>
</dict>
</xsl:for-each>
</array>
</dict>
</xsl:for-each>
</array>
<key>venues</key>
<dict>
<xsl:for-each select="f:venue">
<key><xsl:value-of select="@id" /></key>
<dict>
<key>id</key>
<string><xsl:value-of select="@id" /></string>
<key>title</key>
<string><xsl:value-of select="f:title" /></string>
<key>phone</key>
<string><xsl:value-of select="f:phone" /></string>
<key>geo</key>
<string><xsl:value-of select="f:geo" /></string>
<xsl:for-each select="f:address">
<key>address</key>
<dict>
<key>street</key>
<string><xsl:value-of select="f:street" /></string>
<key>city</key>
<string><xsl:value-of select="f:city" /></string>
<key>zip</key>
<string><xsl:value-of select="f:zip" /></string>
<key>country</key>
<string><xsl:value-of select="f:country" /></string>
</dict>
</xsl:for-each>
</dict>
</xsl:for-each>
</dict>
</dict>
</xsl:for-each>
</plist>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns='http://filmfestapp.com/schema/festival/v1'>
<!--
<xsl:output method="xml" />
<xsl:output indent="yes" />
-->
<!-- unwrap one level, rename node add id attribute -->
<xsl:template match="key[text() = 'venues']">
<xsl:for-each select="following-sibling::dict[1]/key">
<venue>
<xsl:attribute name="id">
<xsl:value-of select="text()" />
</xsl:attribute>
<xsl:apply-templates select="following-sibling::*[1]" />
</venue>
</xsl:for-each>
</xsl:template>
<!-- unwrap one level and rename node -->
<xsl:template match="key[text() = 'sections' or text() = 'movies' or text() = 'directors' or text() = 'actors' or text() = 'producers' or text() = 'scriptwriters' or text() = 'languages' or text() = 'subtitles' or text() = 'screenings']">
<xsl:apply-templates select="following-sibling::*[1]">
<xsl:with-param name="key">
<xsl:value-of select="substring(text(),0,string-length(text()))" />
</xsl:with-param>
</xsl:apply-templates>
</xsl:template>
<!-- unwrap one level and rename node -->
<xsl:template match="key[text() = 'countries']">
<xsl:apply-templates select="following-sibling::*[1]">
<xsl:with-param name="key">country</xsl:with-param>
</xsl:apply-templates>
</xsl:template>
<!-- drop -->
<xsl:template match="key[text() = 'schemaversion' or text() = 'section' or text() = 'sectionId']" />
<!-- rename node -->
<xsl:template match="key[text() = 'description']">
<synopsis><xsl:value-of select="following-sibling::*[1]/text()" /></synopsis>
</xsl:template>
<!-- rename node -->
<xsl:template match="key[text() = 'start']">
<dtstart><xsl:value-of select="following-sibling::*[1]/text()" /></dtstart>
</xsl:template>
<!-- rename node -->
<xsl:template match="key[text() = 'duration']">
<minutes><xsl:value-of select="following-sibling::*[1]/text() div 60" /></minutes>
</xsl:template>
<!-- refill into idref attribute -->
<xsl:template match="key[text() = 'venue']">
<venueref idref="{following-sibling::*[1]/text()}" />
</xsl:template>
<!-- Start converting - generic pattern -->
<xsl:template match="/">
<festival>
<!-- <xsl:for-each select="plist/dict/dict/key">
<venue>
<xsl:attribute name="id">
<xsl:value-of select="text()" />
</xsl:attribute>
<xsl:apply-templates select="following-sibling::*[1]" />
</venue>
</xsl:for-each>
<xsl:for-each select="plist/dict/array/dict">
<section>
<xsl:apply-templates select="key" />
</section>
</xsl:for-each>
--> <xsl:apply-templates select="plist/dict/key" />
</festival>
</xsl:template>
<!-- turn <key>foo</key><value>bar</value> into <foo>bar</foo> -->
<xsl:template match="key">
<xsl:element name="{.}">
<xsl:apply-templates select="following-sibling::*[1]">
<xsl:with-param name="key">
<xsl:value-of select="text()" />
</xsl:with-param>
</xsl:apply-templates>
</xsl:element>
</xsl:template>
<xsl:template match="dict">
<xsl:apply-templates select="key[text() != 'id']" />
</xsl:template>
<xsl:template match="array">
<xsl:param name="key">
item
</xsl:param>
<xsl:for-each select="*">
<xsl:element name="{$key}">
<xsl:apply-templates select="." />
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment