summaryrefslogtreecommitdiff
path: root/foaf/linkedin2foaf.xsl
blob: 2d24452128c471dd84c499500818fc3c82c9660c (plain)
  1. <?xml version='1.0' ?>
  2. <xsl:stylesheet
  3. xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
  4. xmlns:foaf="http://xmlns.com/foaf/0.1/"
  5. xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  6. xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
  7. xmlns:dc="http://purl.org/dc/elements/1.1/"
  8. xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#"
  9. xmlns:doac="http://ramonantonio.net/doac/0.1/"
  10. version='1.0'
  11. >
  12. <xsl:output method="xml" indent="yes" encoding="UTF-8" />
  13. <!--
  14. Author:
  15. Pierre Lindenbaum PhD
  16. plindenbaum@yahoo.fr
  17. http://plindenbaum.blogspot.com
  18. Motivation:
  19. transform a linkedin profile to a FOAF profile
  20. Warning it just works with the current linkedin html (Last updated: 2010-02-08)
  21. Param:
  22. 'geoloc'=false: don't use geonames.org to find position
  23. 'ppd'=false: don't print foaf:personalProfileDocument
  24. Usage:
  25. warning USE a 'www' URL
  26. http://www.linkedin.com...
  27. rather than a local one
  28. http://it.linkedin.com....
  29. http://fr.linkedin.com....
  30. http://en.linkedin.com....
  31. xsltproc \-\-html linkedin2foaf.xsl http://www.linkedin.com/in/lindenbaum
  32. xsltproc \-\-html linkedin2foaf.xsl http://www.linkedin.com/in/dsingh
  33. -->
  34. <!-- use geonames -->
  35. <xsl:param name="geoloc">yes</xsl:param>
  36. <!-- print foaf:personalProfileDocument -->
  37. <xsl:param name="ppd">yes</xsl:param>
  38. <xsl:template match="/">
  39. <rdf:RDF>
  40. <xsl:apply-templates select="html"/>
  41. </rdf:RDF>
  42. </xsl:template>
  43. <xsl:template match="html">
  44. <xsl:apply-templates select="body"/>
  45. </xsl:template>
  46. <xsl:template match="body">
  47. <xsl:variable name="action">
  48. <xsl:value-of select="//a[@class='action' and @rel='nofollow'][1]/@href"/>
  49. </xsl:variable>
  50. <xsl:variable name="lkid" select="concat('http://www.linkedin.com/ppl/webprofile?id=',substring-before(substring-after($action,'id='),'&amp;'))"/>
  51. <xsl:if test="$ppd='yes'">
  52. <xsl:element name="foaf:PersonalProfileDocument">
  53. <xsl:attribute name="rdf:about"><xsl:text></xsl:text></xsl:attribute>
  54. <xsl:element name="foaf:maker">
  55. <xsl:attribute name="rdf:resource">http://code.google.com/p/lindenb/source/browse/trunk/src/xsl/linkedin2foaf.xsl</xsl:attribute>
  56. </xsl:element>
  57. <xsl:element name="foaf:primaryTopic">
  58. <xsl:attribute name="rdf:resource"><xsl:value-of select="$lkid"/></xsl:attribute>
  59. </xsl:element>
  60. </xsl:element>
  61. </xsl:if>
  62. <xsl:element name="foaf:Person">
  63. <xsl:attribute name="rdf:about"><xsl:value-of select="$lkid"/></xsl:attribute>
  64. <xsl:apply-templates/>
  65. <foaf:holdsAccount>
  66. <xsl:element name="foaf:OnlineAccount">
  67. <xsl:attribute name="rdf:about">
  68. <xsl:value-of select="$lkid"/>
  69. </xsl:attribute>
  70. <foaf:accountServiceHomepage rdf:resource="http://www.linkedin.com"/>
  71. </xsl:element>
  72. </foaf:holdsAccount>
  73. </xsl:element>
  74. </xsl:template>
  75. <xsl:template match="h1[@id='name']">
  76. <foaf:name><xsl:value-of select="."/></foaf:name>
  77. <xsl:apply-templates/>
  78. </xsl:template>
  79. <xsl:template match="span[@class='given-name']">
  80. <foaf:givenname><xsl:value-of select="."/></foaf:givenname>
  81. </xsl:template>
  82. <xsl:template match="span[@class='family-name']">
  83. <foaf:family_name><xsl:value-of select="."/></foaf:family_name>
  84. </xsl:template>
  85. <xsl:template match="p[@class='headline title summary']|p[@class='headline title']">
  86. <doac:summary>
  87. <xsl:value-of select="normalize-space(.)"/>
  88. </doac:summary>
  89. </xsl:template>
  90. <xsl:template match="ul[@class='websites']">
  91. <xsl:apply-templates select="li/a[@href]"/>
  92. </xsl:template>
  93. <xsl:template match="div[@id='experience']">
  94. <xsl:for-each select="ul/li">
  95. <doac:experience>
  96. <doac:Experience>
  97. <doac:title><xsl:value-of select="normalize-space(h3)"/></doac:title>
  98. <doac:location><xsl:value-of select="normalize-space(h4[@class='org summary'])"/></doac:location>
  99. <xsl:if test="p[@class='period']/abbr[@class='dtstart']/@title">
  100. <doac:date-starts>
  101. <xsl:value-of select="normalize-space(p[@class='period']/abbr[@class='dtstart']/@title)"/>
  102. </doac:date-starts>
  103. </xsl:if>
  104. <xsl:if test="p[@class='period']/abbr[@class='dtend']/@title">
  105. <doac:date-ends>
  106. <xsl:value-of select="normalize-space(p[@class='period']/abbr[@class='dtend']/@title)"/>
  107. </doac:date-ends>
  108. </xsl:if>
  109. <xsl:if test="p[@class='description']">
  110. <doac:activity>
  111. <xsl:value-of select="normalize-space(p[@class='description'])"/>
  112. </doac:activity>
  113. </xsl:if>
  114. </doac:Experience>
  115. </doac:experience>
  116. </xsl:for-each>
  117. </xsl:template>
  118. <xsl:template match="a[@href][@class='url']">
  119. <xsl:choose>
  120. <xsl:when test="starts-with(@href,'http://twitter.com/')">
  121. <foaf:holdsAccount>
  122. <xsl:element name="foaf:OnlineAccount">
  123. <xsl:attribute name="rdf:about">
  124. <xsl:value-of select="@href"/>
  125. </xsl:attribute>
  126. <foaf:accountName>
  127. <xsl:value-of select="substring-after(@href,'.com/')"/>
  128. </foaf:accountName>
  129. <foaf:accountServiceHomepage rdf:resource="http://twitter.com"/>
  130. </xsl:element>
  131. </foaf:holdsAccount>
  132. </xsl:when>
  133. <xsl:when test="starts-with(@href,'http://friendfeed.com/')">
  134. <foaf:holdsAccount>
  135. <xsl:element name="foaf:OnlineAccount">
  136. <xsl:attribute name="rdf:about">
  137. <xsl:value-of select="@href"/>
  138. </xsl:attribute>
  139. <foaf:accountName>
  140. <xsl:value-of select="substring-after(@href,'.com/')"/>
  141. </foaf:accountName>
  142. <foaf:accountServiceHomepage rdf:resource="http://friendfeed.com"/>
  143. </xsl:element>
  144. </foaf:holdsAccount>
  145. </xsl:when>
  146. <xsl:otherwise>
  147. <xsl:element name="foaf:homepage">
  148. <xsl:attribute name="rdf:resource">
  149. <xsl:value-of select="@href"/>
  150. </xsl:attribute>
  151. </xsl:element>
  152. </xsl:otherwise>
  153. </xsl:choose>
  154. </xsl:template>
  155. <xsl:template match="div[@class='image']">
  156. <xsl:apply-templates select="img[@class='photo']"/>
  157. </xsl:template>
  158. <xsl:template match="img[@class='photo']">
  159. <foaf:depiction>
  160. <xsl:element name="foaf:Image">
  161. <xsl:attribute name="rdf:about">
  162. <xsl:value-of select="@src"/>
  163. </xsl:attribute>
  164. <dc:title><xsl:value-of select="@alt"/></dc:title>
  165. </xsl:element>
  166. </foaf:depiction>
  167. </xsl:template>
  168. <xsl:template match="p[@class='skills']">
  169. <xsl:call-template name="skills">
  170. <xsl:with-param name="s" select="normalize-space(translate(.,',',' '))"/>
  171. </xsl:call-template>
  172. </xsl:template>
  173. <xsl:template name="skills">
  174. <xsl:param name="s"/>
  175. <xsl:choose>
  176. <xsl:when test="contains($s,' ')">
  177. <xsl:call-template name="skills">
  178. <xsl:with-param name="s" select="normalize-space(substring-after($s,' '))"/>
  179. </xsl:call-template>
  180. <doac:skill><xsl:value-of select="substring-before($s,' ')"/></doac:skill>
  181. </xsl:when>
  182. <xsl:otherwise>
  183. <doac:skill><xsl:value-of select="$s"/></doac:skill>
  184. </xsl:otherwise>
  185. </xsl:choose>
  186. </xsl:template>
  187. <xsl:template match="div[@id='education']">
  188. <xsl:for-each select="ul[@class='vcalendar']/li">
  189. <doac:education>
  190. <doac:Education>
  191. <foaf:organization><xsl:value-of select="normalize-space(h3)"/></foaf:organization>
  192. <doac:title><xsl:value-of select="normalize-space(div/p/span[@class='degree'])"/></doac:title>
  193. <xsl:if test="div/p/abbr[@class='dtstart']/@title">
  194. <doac:date-starts>
  195. <xsl:value-of select="normalize-space(div/p/abbr[@class='dtstart']/@title)"/>
  196. </doac:date-starts>
  197. </xsl:if>
  198. <xsl:if test="div/p/abbr[@class='dtend']/@title">
  199. <doac:date-ends>
  200. <xsl:value-of select="normalize-space(div/p/abbr[@class='dtend']/@title)"/>
  201. </doac:date-ends>
  202. </xsl:if>
  203. <xsl:if test="div/p[@class='notes']">
  204. <doac:subject>
  205. <xsl:value-of select="normalize-space(div/p[@class='notes'])"/>
  206. </doac:subject>
  207. </xsl:if>
  208. </doac:Education>
  209. </doac:education>
  210. </xsl:for-each>
  211. </xsl:template>
  212. <xsl:template match="p[@class='locality']">
  213. <xsl:if test="$geoloc='yes'">
  214. <xsl:variable name="s1" select="normalize-space(.)"/>
  215. <xsl:variable name="s2">
  216. <xsl:choose>
  217. <xsl:when test="contains($s1,' Area,')">
  218. <xsl:value-of select="concat(substring-before($s1,' Area,'),substring-after($s1,' Area,'))"/>
  219. </xsl:when>
  220. <xsl:otherwise>
  221. <xsl:value-of select="$s1"/>
  222. </xsl:otherwise>
  223. </xsl:choose>
  224. </xsl:variable>
  225. <xsl:variable name="url" select="concat('http://ws.geonames.org/search?q=',translate($s2,' ','+'),'&amp;maxRows=1')"/>
  226. <xsl:message terminate="no">Downloading <xsl:value-of select="$url"/> ...</xsl:message>
  227. <xsl:apply-templates select="document($url,/geonames)" mode="geo"/>
  228. <xsl:message terminate="no">Done (<xsl:value-of select="$url"/>).</xsl:message>
  229. </xsl:if>
  230. </xsl:template>
  231. <xsl:template match="script|head|meta|link">
  232. </xsl:template>
  233. <xsl:template match="div|span">
  234. <xsl:apply-templates/>
  235. </xsl:template>
  236. <xsl:template match="*|text()">
  237. <xsl:apply-templates/>
  238. </xsl:template>
  239. <xsl:template match="/" mode="geo">
  240. <xsl:apply-templates select="geonames" mode="geo"/>
  241. </xsl:template>
  242. <xsl:template match="geonames" mode="geo">
  243. <xsl:apply-templates select="geoname[1]" mode="geo"/>
  244. </xsl:template>
  245. <xsl:template match="geoname" mode="geo">
  246. <foaf:based_near>
  247. <geo:Point>
  248. <dc:title>
  249. <xsl:value-of select="name"/>
  250. <xsl:text>, </xsl:text>
  251. <xsl:value-of select="countryCode"/>
  252. </dc:title>
  253. <geo:long><xsl:value-of select="lng"/></geo:long>
  254. <geo:lat><xsl:value-of select="lat"/></geo:lat>
  255. </geo:Point>
  256. </foaf:based_near>
  257. </xsl:template>
  258. </xsl:stylesheet>