You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
431 lines
14 KiB
431 lines
14 KiB
<?xml-stylesheet href="http://www.w3.org/StyleSheets/base.css" type="text/css"?>
|
|
<?xml-stylesheet href="http://www.w3.org/2002/02/style-xsl.css" type="text/css"?>
|
|
<xsl:stylesheet
|
|
xmlns:xsl ="http://www.w3.org/1999/XSL/Transform" version="1.0"
|
|
xmlns:h ="http://www.w3.org/1999/xhtml"
|
|
xmlns:dc ="http://purl.org/dc/elements/1.1/"
|
|
xmlns:rdf ="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
xmlns:rdfs ="http://www.w3.org/2000/01/rdf-schema#"
|
|
xmlns:owl ="http://www.w3.org/2002/07/owl#"
|
|
xmlns:dt ="http://www.w3.org/2001/XMLSchema#"
|
|
xmlns:spec ="http://www.w3.org/2002/12/cal/icalSpec#"
|
|
xmlns:cal ="http://www.w3.org/2002/12/cal/icaltzd#"
|
|
>
|
|
|
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
<head>
|
|
<title>Transforming the iCalendar spec to an RDF/OWL ontology</title>
|
|
<link rel="stylesheet" href="http://www.w3.org/StyleSheets/base"/>
|
|
</head>
|
|
<body>
|
|
<div class='head'><a href="/"><img src='/Icons/w3c_home' alt='W3C'/></a></div>
|
|
<h1>Transforming the iCalendar spec to an RDF/OWL ontology</h1>
|
|
|
|
<p>This transformation extracts an RDF/XML schema/ontology
|
|
from an XHTML representation of RFC 2445, iCalendar.</p>
|
|
|
|
<p>It's intended for use with <a
|
|
href="http://www.w3.org/2004/01/rdxh/spec">GRDDL</a> (see also: <a
|
|
href="http://www.w3.org/2003/11/rdf-in-xhtml-demo">demo</a>.)</p>
|
|
|
|
<p>@@TODO: check the output for OWL-DL-happiness, ala
|
|
<a href="http://dannyayers.com/archives/002257.html">Danny A 5Feb</a>.
|
|
capture cardinality constraints; write test cases that fail them;
|
|
get pellet and/or surnia to find the problem.</p>
|
|
|
|
<address>
|
|
<a href="http://www.w3.org/People/Connolly/">Dan Connolly</a> <br />
|
|
<small>$Id: webize2445.xsl,v 1.23 2007/06/28 18:21:54 connolly Exp $</small>
|
|
</address>
|
|
</body>
|
|
</html>
|
|
|
|
<xsl:output method="xml" indent="yes"/>
|
|
|
|
<xsl:variable name="this"
|
|
select='"http://www.w3.org/2002/12/cal/icaltzd"' />
|
|
|
|
<xsl:template match="h:html/h:body">
|
|
<rdf:RDF xml:base="{$this}">
|
|
|
|
<owl:Thing rdf:about="{$this}">
|
|
<dc:source>
|
|
<owl:Thing rdf:about="http://www.ietf.org/rfc/rfc2445.txt"/>
|
|
</dc:source>
|
|
<owl:versionInfo>$Id: webize2445.xsl,v 1.23 2007/06/28 18:21:54 connolly Exp $</owl:versionInfo>
|
|
<owl:versionInfo>subject to change with notice to www-rdf-calendar@w3.org</owl:versionInfo>
|
|
<rdfs:seeAlso rdf:resource="http://www.w3.org/2002/12/cal/"/>
|
|
<rdfs:seeAlso rdf:resource="http://lists.w3.org/Archives/Public/www-rdf-calendar/"/>
|
|
<rdfs:seeAlso rdf:resource="http://esw.w3.org/topic/RdfCalendar"/>
|
|
</owl:Thing>
|
|
|
|
<owl:AnnotationProperty rdf:about="http://www.w3.org/2002/12/cal/icalSpec#valueType"/>
|
|
<owl:AnnotationProperty rdf:about="http://www.w3.org/2002/12/cal/icalSpec#valueListType"/>
|
|
<owl:ObjectProperty rdf:about="http://purl.org/dc/elements/1.1/source"/>
|
|
|
|
<xsl:for-each select='h:div/h:dl[h:dd/@class="ComponentName"]'>
|
|
<xsl:variable name='id' select='h:dt[@id]/@id'/>
|
|
<xsl:variable name='name'
|
|
select='normalize-space(h:dd[@class="ComponentName"])'/>
|
|
<xsl:variable name='label'>
|
|
<xsl:choose>
|
|
<xsl:when test='$name = "VEVENT"'>
|
|
<xsl:text>Event</xsl:text>
|
|
</xsl:when>
|
|
<xsl:when test='$name = "VTODO"'>
|
|
<xsl:text>To-do</xsl:text>
|
|
</xsl:when>
|
|
</xsl:choose>
|
|
</xsl:variable>
|
|
|
|
<xsl:variable name='purpose'
|
|
select='normalize-space(h:dd[@class="Purpose"])'/>
|
|
|
|
<!-- perhaps make icalSpec:Component a subclass of rdfs:Class? -->
|
|
<!-- that would take us outside OWL DL... let's not do that yet -->
|
|
<owl:Class rdf:ID='{$id}'>
|
|
<xsl:if test="string-length($label) > 0">
|
|
<rdfs:label><xsl:value-of select='$label'/></rdfs:label>
|
|
</xsl:if>
|
|
<rdfs:comment><xsl:value-of select='$purpose'/></rdfs:comment>
|
|
|
|
<!-- find properties that can be specified on this component -->
|
|
<xsl:for-each select='//h:div/h:dl[
|
|
.//h:a[@rel="applies-to" and @href=concat("#", $id)]
|
|
]'>
|
|
<xsl:variable name='propid' select='h:dt[@id]/@id'/>
|
|
<rdfs:subClassOf>
|
|
<owl:Restriction>
|
|
<owl:onProperty rdf:resource='{concat("#", $propid)}'/>
|
|
<owl:minCardinality
|
|
rdf:datatype='http://www.w3.org/2001/XMLSchema#integer'
|
|
>0</owl:minCardinality>
|
|
</owl:Restriction>
|
|
</rdfs:subClassOf>
|
|
|
|
<!-- exdate, recurrence-id apply everywhere that rrule does -->
|
|
<xsl:if test='$propid = "rrule"'>
|
|
<rdfs:subClassOf>
|
|
<owl:Restriction>
|
|
<owl:onProperty rdf:resource='{concat("#", "exdate")}'/>
|
|
<owl:minCardinality
|
|
rdf:datatype='http://www.w3.org/2001/XMLSchema#integer'
|
|
>0</owl:minCardinality>
|
|
</owl:Restriction>
|
|
</rdfs:subClassOf>
|
|
<rdfs:subClassOf>
|
|
<owl:Restriction>
|
|
<owl:onProperty rdf:resource='{concat("#", "recurrenceId")}'/>
|
|
<owl:minCardinality
|
|
rdf:datatype='http://www.w3.org/2001/XMLSchema#integer'
|
|
>0</owl:minCardinality>
|
|
</owl:Restriction>
|
|
</rdfs:subClassOf>
|
|
</xsl:if>
|
|
</xsl:for-each>
|
|
|
|
</owl:Class>
|
|
|
|
|
|
<!-- properties defined within a component,
|
|
e.g. standard and daylight -->
|
|
<xsl:for-each select='.//h:a[@rel="def" and @id]'>
|
|
<owl:ObjectProperty rdf:ID='{@id}'>
|
|
<rdfs:label><xsl:value-of select='normalize-space(.)'/></rdfs:label>
|
|
</owl:ObjectProperty>
|
|
</xsl:for-each>
|
|
|
|
|
|
<!-- hmm... are these classes owl:disjoint? -->
|
|
</xsl:for-each>
|
|
|
|
|
|
<xsl:for-each select='h:div/h:dl[h:dd/@class="PropertyName"]'>
|
|
<xsl:variable name='id' select='h:dt[@id]/@id'/>
|
|
<xsl:variable name='purpose'
|
|
select='normalize-space(h:dd[@class="Purpose"])'/>
|
|
<xsl:variable name='valueType'
|
|
select='h:dd/h:a[@rel="value-type"]'/>
|
|
<xsl:variable name='defaultValueType'
|
|
select='h:dd/h:a[@rel="default-value-type"]'/>
|
|
<xsl:variable name='valueListType'
|
|
select='h:dd/h:a[@rel="list-of"]'/>
|
|
|
|
|
|
<xsl:variable name='name'
|
|
select='normalize-space(h:dd[@class="PropertyName"])'/>
|
|
<xsl:variable name='label'>
|
|
<xsl:choose>
|
|
<xsl:when test='$name = "DTSTART"'>
|
|
<xsl:text>start</xsl:text>
|
|
</xsl:when>
|
|
<xsl:when test='$name = "DTEND"'>
|
|
<xsl:text>end</xsl:text>
|
|
</xsl:when>
|
|
<xsl:when test='$name = "SUMMARY"'>
|
|
<xsl:text>summary</xsl:text>
|
|
</xsl:when>
|
|
<xsl:when test='$name = "URL"'>
|
|
<xsl:text>see also</xsl:text>
|
|
</xsl:when>
|
|
<xsl:when test='$name = "LOCATION"'>
|
|
<xsl:text>location</xsl:text>
|
|
</xsl:when>
|
|
<xsl:when test='$name = "ATTENDEE"'>
|
|
<xsl:text>attendee</xsl:text>
|
|
</xsl:when>
|
|
</xsl:choose>
|
|
</xsl:variable>
|
|
<rdf:Description rdf:ID='{$id}'>
|
|
<xsl:if test="string-length($label) > 0">
|
|
<rdfs:label><xsl:value-of select='$label'/></rdfs:label>
|
|
</xsl:if>
|
|
<rdfs:comment><xsl:value-of select='$purpose'/></rdfs:comment>
|
|
|
|
<!-- make summary a subPropertyOf rdfs:label -->
|
|
<xsl:if test='contains($purpose, "summary or subject")'>
|
|
<rdfs:subPropertyOf
|
|
rdf:resource="http://www.w3.org/2000/01/rdf-schema#label" />
|
|
</xsl:if>
|
|
|
|
|
|
<xsl:if test="$valueType">
|
|
<rdfs:comment>
|
|
value type: <xsl:value-of select='$valueType'/>
|
|
</rdfs:comment>
|
|
<spec:valueType>
|
|
<xsl:value-of select='$valueType'/>
|
|
</spec:valueType>
|
|
</xsl:if>
|
|
<xsl:if test="$valueListType">
|
|
<rdfs:comment>
|
|
value type: list of <xsl:value-of select='$valueListType'/>
|
|
</rdfs:comment>
|
|
<spec:valueListType>
|
|
<xsl:value-of select='$valueListType'/>
|
|
</spec:valueListType>
|
|
</xsl:if>
|
|
<xsl:if test="$defaultValueType">
|
|
<rdfs:comment>
|
|
default value type: <xsl:value-of select='$defaultValueType'/>
|
|
</rdfs:comment>
|
|
<spec:valueType>
|
|
<xsl:value-of select='$defaultValueType'/>
|
|
</spec:valueType>
|
|
</xsl:if>
|
|
|
|
<xsl:choose>
|
|
<xsl:when test='$valueType = "INTEGER"
|
|
or $valueType = "integer"'>
|
|
<rdf:type rdf:resource=
|
|
'http://www.w3.org/2002/07/owl#DatatypeProperty'/>
|
|
<rdfs:range>
|
|
<rdfs:Datatype
|
|
rdf:about='http://www.w3.org/2001/XMLSchema#integer'/>
|
|
</rdfs:range>
|
|
</xsl:when>
|
|
|
|
<xsl:when test='$valueType = "DATE-TIME"'>
|
|
<rdf:type rdf:resource=
|
|
'http://www.w3.org/2002/07/owl#DatatypeProperty'/>
|
|
<rdfs:range>
|
|
<rdfs:Datatype
|
|
rdf:about='#Value_DATE-TIME'/>
|
|
</rdfs:range>
|
|
</xsl:when>
|
|
|
|
<!-- perl-esque treatment of utc-offset types -->
|
|
<xsl:when test='$valueType = "TEXT"
|
|
or $valueType = "UTC-OFFSET"
|
|
'>
|
|
<rdf:type rdf:resource=
|
|
'http://www.w3.org/2002/07/owl#DatatypeProperty'/>
|
|
<rdfs:range>
|
|
<rdfs:Datatype
|
|
rdf:about='http://www.w3.org/2001/XMLSchema#string'/>
|
|
</rdfs:range>
|
|
</xsl:when>
|
|
|
|
<xsl:when test='$valueType = "DURATION"
|
|
or $valueType = "PERIOD"
|
|
'>
|
|
<rdf:type rdf:resource=
|
|
'http://www.w3.org/2002/07/owl#ObjectProperty'/>
|
|
<rdfs:range>
|
|
<owl:Class rdf:about="{$valueType/@href}"/>
|
|
</rdfs:range>
|
|
</xsl:when>
|
|
|
|
<xsl:when test='$defaultValueType = "DATE-TIME"'>
|
|
<rdf:type rdf:resource=
|
|
'http://www.w3.org/2002/07/owl#DatatypeProperty'/>
|
|
</xsl:when>
|
|
|
|
<xsl:when test='$defaultValueType = "DURATION"'>
|
|
<rdf:type rdf:resource=
|
|
'http://www.w3.org/2002/07/owl#ObjectProperty'/>
|
|
<rdfs:range>
|
|
<owl:Class>
|
|
<owl:unionOf rdf:parseType="Collection">
|
|
<owl:Class rdf:about="#Value_{$defaultValueType}"/>
|
|
|
|
<!-- might be nice to remove dups -->
|
|
<xsl:for-each select='h:dd//h:a[@rel="allowed-type"]'>
|
|
<owl:Class rdf:about='{@href}'/>
|
|
</xsl:for-each>
|
|
</owl:unionOf>
|
|
</owl:Class>
|
|
</rdfs:range>
|
|
</xsl:when>
|
|
|
|
<xsl:when test='$valueType = "CAL-ADDRESS"'>
|
|
<rdf:type rdf:resource=
|
|
'http://www.w3.org/2002/07/owl#ObjectProperty'/>
|
|
<rdfs:range>
|
|
<owl:Class rdf:about="#Value_CAL-ADDRESS"/>
|
|
</rdfs:range>
|
|
</xsl:when>
|
|
|
|
<xsl:when test='$valueType = "RECUR"'>
|
|
<rdf:type rdf:resource=
|
|
'http://www.w3.org/2002/07/owl#ObjectProperty'/>
|
|
<rdfs:range>
|
|
<owl:Class rdf:about="#Value_RECUR"/>
|
|
</rdfs:range>
|
|
</xsl:when>
|
|
|
|
<!-- hmm... is this use or mention of the URI? -->
|
|
<xsl:when test='$valueType = "URI"
|
|
or $defaultValueType = "URI"'>
|
|
<rdf:type rdf:resource=
|
|
'http://www.w3.org/2002/07/owl#ObjectProperty'/>
|
|
<!-- range is unconstrained; a URI could refer to anything -->
|
|
<!-- or... hmm... constrain it to a Representation? -->
|
|
</xsl:when>
|
|
|
|
<xsl:when test='$valueListType = "FLOAT"'>
|
|
<rdf:type rdf:resource=
|
|
'http://www.w3.org/2002/07/owl#ObjectProperty'/>
|
|
<rdfs:range>
|
|
<!-- We could express the semantics of this class ala:
|
|
:FloatList subClassOf rdf:List,
|
|
[owl:onProperty rdf:first; owl:allValuesFrom :FloatLit ],
|
|
[owl:onProperty rdf:rest; owl:allValuesFrom :FloatList ].
|
|
|
|
I think "list of X" is discussed in the OWL specs
|
|
somewhere.
|
|
-->
|
|
<owl:Class rdf:about="#List_of_Float"/>
|
|
</rdfs:range>
|
|
</xsl:when>
|
|
|
|
<xsl:when test='$valueType or $defaultValueType'>
|
|
<rdf:type rdf:resource=
|
|
'http://www.w3.org/2002/07/owl#ObjectProperty'/>
|
|
<xsl:message>
|
|
unrecognized range.
|
|
value type: <xsl:value-of select="$valueType"/>
|
|
default value type: <xsl:value-of select="$defaultValueType"/>
|
|
</xsl:message>
|
|
</xsl:when>
|
|
|
|
<xsl:otherwise>
|
|
<rdf:type rdf:resource=
|
|
'http://www.w3.org/2002/07/owl#ObjectProperty'/>
|
|
</xsl:otherwise>
|
|
|
|
</xsl:choose>
|
|
|
|
<!-- find components that this property can be specified on -->
|
|
<xsl:variable name='domains' select='.//h:a[@rel="applies-to"]'/>
|
|
<xsl:choose>
|
|
<!-- several of them... make a list -->
|
|
<xsl:when test='count($domains) > 1'>
|
|
<rdfs:domain>
|
|
<owl:Class rdf:nodeID='{concat("DomainOf_", $id)}'>
|
|
<owl:unionOf rdf:parseType="Collection">
|
|
<xsl:for-each select='$domains'>
|
|
<owl:Class rdf:about="{@href}"/>
|
|
</xsl:for-each>
|
|
</owl:unionOf>
|
|
</owl:Class>
|
|
</rdfs:domain>
|
|
</xsl:when>
|
|
|
|
<!-- just one... -->
|
|
<xsl:when test='count($domains) = 1'>
|
|
<rdfs:domain rdf:resource='{$domains/@href}'/>
|
|
</xsl:when>
|
|
|
|
<xsl:when test='contains(h:dd[@class="Conformance"],
|
|
"includes a recurring calendar component") or
|
|
contains(h:dd[@class="Conformance"],
|
|
"containing a recurring calendar component")'>
|
|
<rdfs:domain>
|
|
<owl:Class rdf:about='#DomainOf_rrule'/>
|
|
</rdfs:domain>
|
|
</xsl:when>
|
|
|
|
<xsl:otherwise>
|
|
<!-- pass -->
|
|
</xsl:otherwise>
|
|
</xsl:choose>
|
|
</rdf:Description>
|
|
|
|
</xsl:for-each>
|
|
|
|
<xsl:for-each select='h:div/h:dl[h:dd/@class="ValueName"]'>
|
|
<!-- parameters -->
|
|
<xsl:for-each select='.//h:a[@rel="def" and @id]'>
|
|
<owl:DatatypeProperty rdf:ID='{@id}'>
|
|
<rdfs:label><xsl:value-of select='normalize-space(.)'/></rdfs:label>
|
|
</owl:DatatypeProperty>
|
|
</xsl:for-each>
|
|
</xsl:for-each>
|
|
|
|
<xsl:for-each select='h:div/h:dl[h:dd/@class="ParameterName"]'>
|
|
<xsl:variable name='id' select='h:dt[@id]/@id'/>
|
|
<xsl:if test='$id != "value"'> <!-- mapped to rdf datatypes -->
|
|
<xsl:variable name='name'
|
|
select='normalize-space(h:dd[@class="ParameterName"])'/>
|
|
<xsl:variable name='purpose'
|
|
select='normalize-space(h:dd[@class="Purpose"])'/>
|
|
<owl:DatatypeProperty rdf:ID='{$id}'>
|
|
<rdfs:comment><xsl:value-of select='$purpose'/></rdfs:comment>
|
|
|
|
</owl:DatatypeProperty>
|
|
</xsl:if>
|
|
</xsl:for-each>
|
|
|
|
|
|
<!-- sorta hard-coded... -->
|
|
<xsl:for-each select='h:div[contains(h:h2, "4.4 iCalendar Object")]'>
|
|
<owl:Class rdf:ID="Vcalendar">
|
|
<rdfs:label>VCALENDAR</rdfs:label>
|
|
</owl:Class>
|
|
<owl:ObjectProperty rdf:ID="component">
|
|
<!-- hmm... domain is bigger than just Vcalendar, isn't it? -->
|
|
</owl:ObjectProperty>
|
|
|
|
<rdfs:Datatype rdf:about="#dateTime" />
|
|
<owl:ObjectProperty rdf:about="#calAddress" />
|
|
|
|
<owl:DatatypeProperty rdf:about="http://www.w3.org/1999/02/22-rdf-syntax-ns#value">
|
|
<!-- also... Value_DURATION onProperty rdf:value;
|
|
allValuesFrom xsdt:duration.
|
|
but that's outside DL too.
|
|
-->
|
|
</owl:DatatypeProperty>
|
|
</xsl:for-each>
|
|
|
|
</rdf:RDF>
|
|
|
|
</xsl:template>
|
|
|
|
|
|
<!-- don't pass text thru -->
|
|
<xsl:template match="text()|@*">
|
|
</xsl:template>
|
|
|
|
|
|
</xsl:stylesheet>
|