<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
	xmlns="http://xmlns.com/foaf/0.1/"
	xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
	xmlns:xhtml="http://www.w3.org/1999/xhtml"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	xmlns:xfn="http://gmpg.org/xfn/11#"
	xmlns:dc="http://purl.org/dc/terms/"
	exclude-result-prefixes="xhtml"
        version="1.0">

<!-- 
$Id: hFoaf.xsl,$Version 1.0 *stable* Sunday, May 11 2008 09:15 PM martin mcevoy.
$Description An attempt at enabling Social Network Portability usigng hCard, XFN, XFolk and GRDDL. Inspired by dan connolly's grokXFN.xsl. http://www.w3.org/2003/12/rdf-in-xhtml-xslts/grokXFN.xsl -->

<xsl:strip-space elements="*"/>
<xsl:output method="xml" 
		   indent="yes" 
		   encoding="UTF-8" 
		   media-type="application/rdf+xml"/>

<!-- find first occurrence of a hcard with rel="me" there should only be one-->
<xsl:param name="vcard" select="//xhtml:*[contains(concat(' ',normalize-space(@class),' '),' vcard ') and descendant::xhtml:a[contains(concat(' ',normalize-space(@rel),' '),' me ')]]"/>

<!-- Low Hanging Fruit 	<link rel="me" href="http://your.url/" />  in the <head></head> of your document -->
<xsl:param name="posh-uri" select="/*//xhtml:link[contains(concat(' ',normalize-space(@rel),' '),' me ')]"/>

<xsl:param name="title" select="//xhtml:title"/>

<xsl:param name="base-uri">
<xsl:choose>
	<xsl:when test="$posh-uri" >
	  <xsl:value-of select="$posh-uri" />
	</xsl:when>
<!-- no posh-uri base uri set by processor as the referring url-->
	<xsl:otherwise>
		<xsl:value-of select="''"/>
	</xsl:otherwise>
</xsl:choose>
</xsl:param>

<!-- Get id from hcard else me  -->
<xsl:param name="id">
<xsl:choose>
	<xsl:when test="$vcard/@id" >
	  <xsl:value-of select="$vcard/@id" />
	</xsl:when>
	<xsl:otherwise>
		<xsl:text>me</xsl:text>
	</xsl:otherwise>
</xsl:choose>
</xsl:param>

<!-- Limit output to only one  -->
<xsl:param name="limit">1</xsl:param>

<xsl:template match="/">
  <rdf:RDF>
    <xsl:apply-templates/>
  </rdf:RDF>
</xsl:template>

<xsl:template match="xhtml:html">
<xsl:param name="about"/>
<xsl:choose>
    <xsl:when test="$vcard">
	<xsl:for-each select="$vcard[position() &lt;= $limit]">
		<PersonalProfileDocument rdf:about="{$about}">
			<dc:title><xsl:value-of select="$title"/></dc:title>
			<maker rdf:resource="#{$id}"/>
    			<primaryTopic rdf:resource="#{$id}"/>
		</PersonalProfileDocument>
 	 	<xsl:element name='Person'>
			<xsl:attribute name="rdf:ID">
	  			<xsl:value-of select="$id" />
			</xsl:attribute>
			<xsl:call-template name="name"/>
			<xsl:call-template name="firstName"/>
			<xsl:call-template name="familyName"/>
			<xsl:call-template name="nickName"/>
			<xsl:call-template name="homelinks"/>
			<xsl:call-template name="mailbox"/>
			<xsl:call-template name="sha1"/>
			<xsl:call-template name="photo"/>
			<xsl:call-template name="geo"/>
			<xsl:call-template name="friends"/>
			<xsl:call-template name="knows"/>
			<xsl:call-template name="links"/>
  		</xsl:element>
  	</xsl:for-each>
    </xsl:when>
    <!-- error or no hcard with rel="me" found stop processing -->
    <xsl:otherwise>
	<xsl:text>Oops! something goes wrong :( maybe no single hcard found with rel-me or invalid XHTML</xsl:text>
    </xsl:otherwise>
</xsl:choose>
</xsl:template>


<!-- ==============================================Temaplates===============================================-->

<!-- Name =>  class="fn" -->
<xsl:template name="name">
<xsl:param name="fn" select="descendant::xhtml:*[contains(concat(' ',normalize-space(@class),' '),' fn ')]"/>
	<xsl:if test="$fn">
		<xsl:element name='name'>
			<xsl:value-of select="$fn"/>
		</xsl:element>
	</xsl:if>
</xsl:template>


<!-- givenname => @class="given-name" -->
<xsl:template name="firstName">
<xsl:param name="firstname" select="descendant::xhtml:*[contains(concat(' ',normalize-space(@class),' '),' given-name ')]"/>
	<xsl:if test="$firstname">
		<xsl:element name='givenname'>
			<xsl:value-of select="$firstname"/>
		</xsl:element>
	</xsl:if>
</xsl:template>

<!-- family_name => @class="family-name" -->
<xsl:template name="familyName">
<xsl:param name="surname" select="descendant::xhtml:*[contains(concat(' ',normalize-space(@class),' '),' family-name ')]"/>
	<xsl:if test="$surname">
		<xsl:element name='family_name'>
			<xsl:value-of select="$surname"/>
		</xsl:element>
	</xsl:if>
</xsl:template>

<!-- nic => @class="nickname" -->
<xsl:template name="nickName">
<xsl:param name="nickname" select="descendant::xhtml:*[contains(concat(' ',normalize-space(@class),' '),' nickname ')]"/>
	<xsl:if test="$nickname">
		<xsl:element name='nick'>
			<xsl:value-of select="$nickname"/>
		</xsl:element>
	</xsl:if>
</xsl:template>

<!-- workplaceHomepage => class="url org" -->
<xsl:template name="homelinks">
<xsl:param name="org" select="descendant::xhtml:*[contains(concat(' ',normalize-space(@class),' '),' org ')]"/>
<xsl:choose>
	<xsl:when test="$org">
		<xsl:element name='workplaceHomepage'>
			<xsl:attribute name='rdf:resource'>
	  			<xsl:value-of select="$org/@href"/>
			</xsl:attribute>
		</xsl:element>
	</xsl:when>
	<xsl:otherwise>
		<xsl:call-template name="weblog"/>
	</xsl:otherwise>
</xsl:choose>
</xsl:template>


<!-- homepage => $posh-uri -->
<xsl:template name="weblog">
<xsl:param name="link" select="$posh-uri|descendant::xhtml:*[contains(concat(' ',normalize-space(@class),' '),' url ')]"/>
	<xsl:if test="$link">
		<xsl:element name='homepage'>
			<xsl:attribute name='rdf:resource'>
	  			<xsl:value-of select="$link/@href"/>
			</xsl:attribute>
		</xsl:element>
	</xsl:if>
</xsl:template>

<!-- mbox => class="email"/@href  -->
<xsl:template name="mailbox">
<xsl:param name="email" select="descendant::xhtml:*[contains(concat(' ',normalize-space(@class),' '),' email ')]"/>
	<xsl:if test="$email">
		<xsl:element name='mbox'>
			<xsl:attribute name='rdf:resource'>
				<xsl:value-of select="$email/@href"/>
			</xsl:attribute>
		</xsl:element>
	</xsl:if>
</xsl:template>

<!--  mbox_sha1sum => class="email"/@id -->
<xsl:template name="sha1">
<xsl:param name="uid" select="descendant::xhtml:*[contains(concat(' ',normalize-space(@class),' '),' email ')]"/>
	<xsl:if test="$uid">
	<xsl:for-each select="$uid">
		<xsl:if test="substring-after(normalize-space(@id),'sha1:')">
			<xsl:element name='mbox_sha1sum'>
				<xsl:value-of select="substring-after(normalize-space(@id),'sha1:')"/>
			</xsl:element>
		</xsl:if>
	</xsl:for-each>
	</xsl:if>
</xsl:template>

<!-- depiction =>  @class="photo"  -->
<xsl:template name="photo">
<xsl:param name="image" select="descendant::xhtml:*[contains(concat(' ',normalize-space(@class),' '),' photo ')]"/>
 <xsl:if test="$image">
  <xsl:for-each select="$image">
		<xsl:choose>
			<xsl:when test="substring-before(@src,':') = 'http'" >
			<xsl:element name='img'>
  				<xsl:attribute name='rdf:resource'>
	 	 			<xsl:value-of select="$image/@src" />
				</xsl:attribute>
			</xsl:element>
			</xsl:when>
			<xsl:otherwise>
			<xsl:element name='img'>
  				<xsl:attribute name='rdf:resource'>
	  				<xsl:value-of select="$base-uri"/>
	 	 			<xsl:value-of select="$image/@src" />
				</xsl:attribute>
			</xsl:element>
			</xsl:otherwise>
		</xsl:choose>
    </xsl:for-each>
  </xsl:if>
</xsl:template>

<!-- geo:Point =>  @class="geo"  geo:lat @class="latitude"/@title  geo:long @class="longitude"/@title -->
<xsl:template name="geo">
<xsl:param name="location" select="descendant::xhtml:*[contains(concat(' ',normalize-space(@class),' '),' geo ')]"/>
	<xsl:if test="$location">
	<xsl:for-each select="$location">
  		<xsl:element name='based_near'>
  		<xsl:element name='geo:Point'>
			<xsl:attribute name="rdf:about">
	  			<xsl:value-of select="$base-uri"/>
					<xsl:text>#</xsl:text>
	 	 			<xsl:choose>
						<xsl:when test="@id" >
	  						<xsl:value-of select="@id" />
						</xsl:when>
						<xsl:otherwise>
							<xsl:text>geo</xsl:text>
						</xsl:otherwise>
					</xsl:choose>
			</xsl:attribute>
			<xsl:element name='geo:lat'>
				<xsl:value-of select=".//xhtml:abbr[contains(concat(' ',normalize-space(@class),' '),' latitude ')]/@title"/>
			</xsl:element>
		 	<xsl:element name='geo:long'>
				<xsl:value-of select=".//xhtml:abbr[contains(concat(' ',normalize-space(@class),' '),' longitude ')]/@title"/>
			</xsl:element>
		<rdf:type rdf:resource="http://www.w3.org/2000/10/swap/pim/contact#ContactLocation"/>
		</xsl:element>
		</xsl:element>
	</xsl:for-each>
	</xsl:if>
</xsl:template>

<!-- Build XFN Friend Links -->
<xsl:template name="friends">
<xsl:call-template name="rel-Links">
	<xsl:with-param name="rel" select='"friend"'/>
</xsl:call-template>
<xsl:call-template name="rel-Links">
	<xsl:with-param name="rel" select='"colleague"'/>
</xsl:call-template>
<xsl:call-template name="rel-Links">
	<xsl:with-param name="rel" select='"co-worker"'/>
</xsl:call-template>
<xsl:call-template name="rel-Links">
	<xsl:with-param name="rel" select='"acquaintance"'/>
</xsl:call-template>
<xsl:call-template name="rel-Links">
	<xsl:with-param name="rel" select='"met"'/>
</xsl:call-template>
<xsl:call-template name="rel-Links">
	<xsl:with-param name="rel" select='"muse"'/>
</xsl:call-template>
<xsl:call-template name="rel-Links">
	<xsl:with-param name="rel" select='"contact"'/>
</xsl:call-template>
</xsl:template>

<xsl:template name="rel-Links">
<xsl:param name="rel"/>
  <xsl:for-each select="/*//xhtml:a[contains(concat(' ', @rel, ' '), concat(' ', $rel, ' '))]">
  	<xsl:element name='xfn:{$rel}'>
		<xsl:attribute name="rdf:resource"><xsl:value-of select="@href"/></xsl:attribute>
  	</xsl:element>
  </xsl:for-each>
</xsl:template>

<!-- interest and Document => if@class="taggedlink"(xfolk) else@rel="bookmark" (hAtom) -->
<xsl:template name="links">
      <xsl:call-template name="bookmarks">
	<xsl:with-param name="class" select='"taggedlink"'/>
	<xsl:with-param name="link" select='"bookmark"'/>
      </xsl:call-template>
</xsl:template>

<xsl:template name="bookmarks">
  <xsl:param name="link"/>
  <xsl:param name="class"/>
  <xsl:param name="xfolk" select="/*//xhtml:a[contains(concat(' ', @class, ' '),    concat(' ', $class, ' '))]"/>
  <xsl:param name="bookmarks" select="/*//xhtml:a[contains(concat(' ', @rel, ' '),    concat(' ', $link, ' '))]"/>
  <xsl:choose>
	<xsl:when test="$xfolk">
  		<xsl:for-each select="$xfolk">
			<xsl:call-template name="entry"/>
  		</xsl:for-each>
	</xsl:when>
	<xsl:otherwise>
  		<xsl:for-each select="$bookmarks">
			<xsl:call-template name="entry"/>
  		</xsl:for-each>
	</xsl:otherwise>
  </xsl:choose>    
</xsl:template>

<xsl:template name="entry">
  <xsl:element name='interest'>
  	<xsl:element name='Document'>
    	<xsl:attribute name="rdf:about">
		<xsl:choose>
			<xsl:when test="substring-before(@href,':') = 'http'" >
				<xsl:value-of select="@href"/>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$base-uri"/>
				<xsl:value-of select="@href"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:attribute>
	<xsl:element name='dc:title'>
		<xsl:value-of select="."/>
	</xsl:element>
	</xsl:element>
   </xsl:element>
</xsl:template>

<!-- Who do they know XFN -->
<xsl:template name="knows">
  <xsl:for-each select="/*//xhtml:a[contains(concat(' ', @rel, ' '), concat(' ', 'friend', ' '))]|/*//xhtml:a[contains(concat(' ', @rel, ' '), concat(' ', 'colleague', ' '))]|/*//xhtml:a[contains(concat(' ', @rel, ' '), concat(' ', 'acquaintance', ' '))]|/*//xhtml:a[contains(concat(' ', @rel, ' '), concat(' ', 'co-worker', ' '))]|/*//xhtml:a[contains(concat(' ', @rel, ' '), concat(' ', 'met', ' '))]|/*//xhtml:a[contains(concat(' ', @rel, ' '), concat(' ', 'muse', ' '))]|/*//xhtml:a[contains(concat(' ', @rel, ' '), concat(' ', 'contact', ' '))]">
  <xsl:element name='knows'>
	<xsl:element name='Person'>
    		<xsl:attribute name="rdf:about"><xsl:value-of select="@href"/></xsl:attribute>				
			<xsl:element name='name'>
	 	 		<xsl:choose>
					<xsl:when test="@title" >
	  					<xsl:value-of select="@title" />
					</xsl:when>
					<xsl:otherwise>
						<xsl:value-of select="."/>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:element>
			<xsl:element name='weblog'>
				<xsl:attribute name="rdf:resource"><xsl:value-of select="@href"/></xsl:attribute>
			</xsl:element>
  	</xsl:element>
  </xsl:element>
  </xsl:for-each>
</xsl:template>


<!-- strip text -->
<xsl:template match="text()"></xsl:template>
</xsl:stylesheet>
