xfn-to-foaf: Difference between revisions
(→Related Pages: Add Richard Cyganiak's guide) |
m (Replace <entry-title> with {{DISPLAYTITLE:}}) |
||
(5 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
{{DISPLAYTITLE:XFN → FOAF}} | |||
{{TOC-right}} | {{TOC-right}} | ||
by [[User:TobyInk|Toby Inkster]] | by [[User:TobyInk|Toby Inkster]] | ||
(Contributors: Gabriele Renzi) | |||
<p> </p> | <p> </p> | ||
Line 21: | Line 23: | ||
#* (Parsers {{should}} impose a depth limit for crawling.) | #* (Parsers {{should}} impose a depth limit for crawling.) | ||
# If no hCard for the subject has been found, the subject is a person represented by the following RDF triples: | # If no hCard for the subject has been found, the subject is a person represented by the following RDF triples: | ||
<pre><nowiki>:bnode01 a foaf:Person; | <pre><nowiki>_:bnode01 a foaf:Person; | ||
foaf:page <http://alice.example.net>.</nowiki></pre> | foaf:page <http://alice.example.net>.</nowiki></pre> | ||
Line 32: | Line 34: | ||
For <code>rel="me"</code> the predicate is <code>foaf:page</code>. | For <code>rel="me"</code> the predicate is <code>foaf:page</code>. | ||
For other relationships, the local name of the predicate is the same as the rel value, and the namespace URI is defined as <code><nowiki>http:// | For other relationships, the local name of the predicate is the same as the rel value, and the namespace URI is defined as <code><nowiki>http://vocab.sindice.com/xfn#</nowiki></code>. Many non-me XFN values can be considered to be refinements of foaf:knows. As an example, the fully qualified URIs for the predicates associated with <code><nowiki>rel="met friend"</nowiki></code> are: | ||
* <code><nowiki>http:// | * <code><nowiki>http://vocab.sindice.com/xfn#met</nowiki></code> | ||
* <code><nowiki>http:// | * <code><nowiki>http://vocab.sindice.com/xfn#friend</nowiki></code> | ||
* <code><nowiki>http://xmlns.com/foaf/0.1/knows</nowiki></code> | * <code><nowiki>http://xmlns.com/foaf/0.1/knows</nowiki></code> | ||
Line 46: | Line 48: | ||
# In the high-bandwidth situation, parsers {{may}} follow the link target to look for a representative hCard for the object. | # In the high-bandwidth situation, parsers {{may}} follow the link target to look for a representative hCard for the object. | ||
#* (Parsers {{may}} then further follow rel="me" links from <nowiki>http://bob.example.net</nowiki> in order to find a "better" representative hCard for Bob.) | #* (Parsers {{may}} then further follow rel="me" links from <nowiki>http://bob.example.net</nowiki> in order to find a "better" representative hCard for Bob.) | ||
# If no hCard representing the object of the relationship has been found, then the object is taken to be a <code>foaf:Person</code> with a <code>foaf:name</code> corresponding to the link text and, depending on the kind of link provided in the <code>href</code> attribute, a <code>foaf:mbox</code> (for "mailto:" links), <code>foaf:mbox_sha1sum</code> (for "urn:sha1:" URLs), <code>foaf:img</code> (image links, determined by <code>type</code> attribute or HTTP headers, not by file name) or <code>foaf:page</code> (all other links). Our example would generate the following triples: <pre><nowiki>:bnode02 a foaf:Person; | # If no hCard representing the object of the relationship has been found, then the object is taken to be a <code>foaf:Person</code> with a <code>foaf:name</code> corresponding to the link text and, depending on the kind of link provided in the <code>href</code> attribute, a <code>foaf:mbox</code> (for "mailto:" links), <code>foaf:mbox_sha1sum</code> (for "urn:sha1:" URLs), <code>foaf:img</code> (image links, determined by <code>type</code> attribute or HTTP headers, not by file name) or <code>foaf:page</code> (all other links). Our example would generate the following triples: | ||
<pre><nowiki>_:bnode02 a foaf:Person; | |||
foaf:page <http://bob.example.net>; | foaf:page <http://bob.example.net>; | ||
foaf:name "Bob Smith".</nowiki></pre> | foaf:name "Bob Smith".</nowiki></pre> | ||
Line 52: | Line 56: | ||
A parser which understands RDFa or other semantics may use additional techniques to determine the object of the link, but those are beyond the scope of the Microformats wiki. | A parser which understands RDFa or other semantics may use additional techniques to determine the object of the link, but those are beyond the scope of the Microformats wiki. | ||
'''Is the link text really a person's name?''' sometimes it will be, sometimes it won't. If the link is part of an hCard which has used <code><nowiki><a class="fn url" ...></nowiki></code>, then it should be safe to suppose that it is a name, but at other times this is more of a risk. Often the link text will be a nickname. This is OK, as the definition of the <code>foaf:name</code> term is sufficiently broad to cover these cases. In other cases, it might not be a name at all. Depending on your application's needs, you may want to consider using <code>rdfs:label</code> instead of <code>foaf:name</code> or simply ignoring the link text completely. | |||
== Example == | == Example == | ||
Line 129: | Line 133: | ||
<pre><nowiki> | <pre><nowiki> | ||
<?xml version="1.0"?> | <?xml version="1.0"?> | ||
<rdf:RDF xmlns="http://xmlns.com/foaf/0.1/" | <rdf:RDF xmlns:foaf="http://xmlns.com/foaf/0.1/" | ||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | ||
xmlns:xfn="http:// | xmlns:xfn="http://vocab.sindice.com/xfn#" | ||
xmlns | xmlns="http://www.w3.org/2006/vcard/ns#"> | ||
<!-- Alice --> | <!-- Alice --> | ||
< | <VCard rdf:nodeID="bnode01"> | ||
<!-- data from Alice's hCard --> | <!-- data from Alice's hCard --> | ||
< | <fn>Alice Jones</fn> | ||
< | <adr rdf:parseType="Resource"> | ||
< | <locality>Sydney</locality> | ||
< | <country-name>Australia</country-name> | ||
</ | </adr> | ||
< | <url rdf:resource="http://alice.example.com/blog/" /> | ||
<!-- data from Alice's XFN links --> | <!-- data from Alice's XFN links --> | ||
<page rdf:resource="http://alice.example.com/blog/" /> | <foaf:page rdf:resource="http://alice.example.com/blog/" /> | ||
<knows rdf:nodeID="bnode02" /> | <foaf:knows rdf:nodeID="bnode02" /> | ||
<xfn:met rdf:nodeID="bnode02" /> | <xfn:met rdf:nodeID="bnode02" /> | ||
<xfn:friend rdf:nodeID="bnode02" /> | <xfn:friend rdf:nodeID="bnode02" /> | ||
<knows rdf:nodeID="bnode03" /> | <foaf:knows rdf:nodeID="bnode03" /> | ||
<xfn:met rdf:nodeID="bnode03" /> | <xfn:met rdf:nodeID="bnode03" /> | ||
<xfn:co-worker rdf:nodeID="bnode03" /> | <xfn:co-worker rdf:nodeID="bnode03" /> | ||
<knows rdf:nodeID="bnode04" /> | <foaf:knows rdf:nodeID="bnode04" /> | ||
<xfn:met rdf:nodeID="bnode04" /> | <xfn:met rdf:nodeID="bnode04" /> | ||
<xfn:friend rdf:nodeID="bnode04" /> | <xfn:friend rdf:nodeID="bnode04" /> | ||
<xfn:neighbor rdf:nodeID="bnode04" /> | <xfn:neighbor rdf:nodeID="bnode04" /> | ||
<knows rdf:nodeID="bnode05" /> | <foaf:knows rdf:nodeID="bnode05" /> | ||
<xfn:met rdf:nodeID="bnode05" /> | <xfn:met rdf:nodeID="bnode05" /> | ||
</ | </VCard> | ||
<!-- Bob, data from hCard --> | <!-- Bob, data from hCard --> | ||
< | <VCard rdf:nodeID="bnode02"> | ||
< | <fn>Bob Smith</fn> | ||
< | <url rdf:resource="http://bob.example.net" /> | ||
</ | </VCard> | ||
<!-- Carol, implied data --> | <!-- Carol, implied data --> | ||
<Person rdf:nodeID="bnode03"> | <foaf:Person rdf:nodeID="bnode03"> | ||
<name>Carol Brown</name> | <foaf:name>Carol Brown</foaf:name> | ||
<page rdf:resource="http://carol.example.net" /> | <foaf:page rdf:resource="http://carol.example.net" /> | ||
</Person> | </foaf:Person> | ||
<!-- Dave, implied data --> | <!-- Dave, implied data --> | ||
<Person rdf:nodeID="bnode04"> | <foaf:Person rdf:nodeID="bnode04"> | ||
<name>Dave Wong</name> | <foaf:name>Dave Wong</foaf:name> | ||
<page rdf:resource="http://dave.example.net" /> | <foaf:page rdf:resource="http://dave.example.net" /> | ||
</Person> | </foaf:Person> | ||
<!-- Eve, data from hCard --> | <!-- Eve, data from hCard --> | ||
< | <VCard rdf:nodeID="bnode05"> | ||
< | <fn>Eve Ville</fn> | ||
< | <url rdf:resource="http://eve.example.net" /> | ||
< | <uid>http://eve.example.net"</uid> | ||
< | <email rdf:resource="mailto:eve@example.net" /> | ||
</ | </VCard> | ||
</rdf:RDF> | </rdf:RDF> | ||
</nowiki></pre> | </nowiki></pre> | ||
Note that some personal data for contacts is expressed in the FOAF vocabulary, and some information is expressed in vCard/hCard vocabulary. User agents may use OWL or another technique to draw equivalencies between vocabularies, such as taking <code> | Note that some personal data for contacts is expressed in the FOAF vocabulary, and some information is expressed in vCard/hCard vocabulary. User agents may use OWL or another technique to draw equivalencies between vocabularies, such as taking <code>fn</code> to be equivalent to <code>foaf:name</code>. | ||
== Organisation hCards and XFN == | == Organisation hCards and XFN == | ||
Line 238: | Line 242: | ||
=== Other === | === Other === | ||
* [http://xen.adactio.com/ XHTML Enemies Network] - spoof of XFN. Can be easily implemented using the same algorithm. | * [http://xen.adactio.com/ XHTML Enemies Network] - spoof of XFN. Can be easily implemented using the same algorithm. | ||
** [http://buzzword.org.uk/rdf/xen XHTML Enemies Network in RDF] | |||
* [[xpn|XHTML Professionals Network]] - proposed extension to XFN to deal with corporate relationships. When/if completed, will probably be implementable using the algorithm on this page. | * [[xpn|XHTML Professionals Network]] - proposed extension to XFN to deal with corporate relationships. When/if completed, will probably be implementable using the algorithm on this page. |
Latest revision as of 16:35, 18 July 2020
by Toby Inkster
(Contributors: Gabriele Renzi)
A number of people have expressed an interest in extracting RDF-like data from XFN and hCard. The problem is that while XFN is interpreted as representing a relationship between two people, it actually encodes a relationship between two URIs.
This page describes a technique for figuring out which people these URIs represent. It is not an attempt to describe a new specification or standard, but rather, a set of best practices. Two algorithms are described: a "high-bandwidth" version which requires web crawling, and a "low-bandwidth" version which uses only the information found on the initial page.
For most of the examples on this page, the following XFN link will be used:
<a rel="friend met" href="http://bob.example.net">Bob Smith</a>
which has been found on Alice Jones' web page at http://alice.example.net.
Determining the subject
- Find the representative hCard for the current page.
- In the high-bandwidth situation, parsers MAY crawl
rel=me
links in order to find a "better" representative hCard, where the meaning of "better" is to be defined by the parser itself.- (Parsers SHOULD impose a depth limit for crawling.)
- If no hCard for the subject has been found, the subject is a person represented by the following RDF triples:
_:bnode01 a foaf:Person; foaf:page <http://alice.example.net>.
A parser which understands RDFa or other semantics may use additional techniques to determine the subject of the link, but those are beyond the scope of the Microformats wiki.
Determining the predicate
This is the easiest step.
For rel="me"
the predicate is foaf:page
.
For other relationships, the local name of the predicate is the same as the rel value, and the namespace URI is defined as http://vocab.sindice.com/xfn#
. Many non-me XFN values can be considered to be refinements of foaf:knows. As an example, the fully qualified URIs for the predicates associated with rel="met friend"
are:
http://vocab.sindice.com/xfn#met
http://vocab.sindice.com/xfn#friend
http://xmlns.com/foaf/0.1/knows
Which XFN values are refinements of foaf:knows
? This is a matter of debate. Although normally, say, a parent and child will have a close relationship, there are instances where they may have never met, and not know each other at all. The current list of XFN values which I treat as refinements of foaf:knows
are: acquaintance, friend, met, co-resident, spouse, crush, date and sweetheart. Depending upon your application, you may wish to narrow or broaden your scope.
Determining the object
- If the link element is a descendant of an element with
class="vcard"
which is not the representative hCard for the page, then this hCard is taken to represent the person who is the object of the relationship. - In the high-bandwidth situation, parsers MAY follow the link target to look for a representative hCard for the object.
- (Parsers MAY then further follow rel="me" links from http://bob.example.net in order to find a "better" representative hCard for Bob.)
- If no hCard representing the object of the relationship has been found, then the object is taken to be a
foaf:Person
with afoaf:name
corresponding to the link text and, depending on the kind of link provided in thehref
attribute, afoaf:mbox
(for "mailto:" links),foaf:mbox_sha1sum
(for "urn:sha1:" URLs),foaf:img
(image links, determined bytype
attribute or HTTP headers, not by file name) orfoaf:page
(all other links). Our example would generate the following triples:
_:bnode02 a foaf:Person; foaf:page <http://bob.example.net>; foaf:name "Bob Smith".
A parser which understands RDFa or other semantics may use additional techniques to determine the object of the link, but those are beyond the scope of the Microformats wiki.
Is the link text really a person's name? sometimes it will be, sometimes it won't. If the link is part of an hCard which has used <a class="fn url" ...>
, then it should be safe to suppose that it is a name, but at other times this is more of a risk. Often the link text will be a nickname. This is OK, as the definition of the foaf:name
term is sufficiently broad to cover these cases. In other cases, it might not be a name at all. Depending on your application's needs, you may want to consider using rdfs:label
instead of foaf:name
or simply ignoring the link text completely.
Example
The following example is assumed to have been found at http://alice.example.net. For simplicity's sake, we assume the low-bandwidth situation.
<html lang="en"> <title>Alice Jones</title> <div class="vcard"> <h1 class="fn">Alice Jones</h1> <p class="adr"> <span class="locality">Sydney</span>, <span class="country-name">Australia</span>. </p> <p> <a href="http://alice.example.com/blog/" rel="me" class="url"> Alice's Blog </a> </p> </div> <h2>Friends & Contacts</h2> <ul> <li class="vcard"> <a class="fn url" href="http://bob.example.net" rel="friend met"> Bob Smith </a> </li> <li> <a href="http://carol.example.net" rel="co-worker met"> Carol Brown </a> </li> <li> <a href="http://dave.example.net" rel="friend neighbor met"> Dave Wong </a> </li> <li> <a href="http://eve.example.net" rel="adversary met"> Eve Ville </a> </li> </ul> <address class="vcard"> Page maintained by <a href="http://eve.example.net" class="url uid" >Eve Ville</a>. Contact <a class="email" href="mailto:eve@example.net" >eve@example.net</a> for corrections. (I know I'm not the most trustworthy of sources.) </address> </html>
The subject of all the XFN links on the page is the hCard for Alice Jones at the top of the page. This is determined in step two of the representative hCard parsing procedure because it contains rel="me"
.
The next XFN link is the one labelled "Bob Smith". Because the link is part of an hCard, the person described by the hCard is the object of the link.
For the next two XFN links, there exist no hCards that represent the objects. We can gather some information about them from the link element itself: their foaf:name
and foaf:page
. (Note that FOAF defines foaf:name very loosely, so it's OK if the link text is a nickname.)
Although at first glance the XFN link for Eve Ville looks similar, there is in fact an hCard later on in the page with a UID matching the XFN link target, so using rule #2 for determining the object, we use this hCard as the object of the XFN relationship. Note that "adversary" is not an XFN rel value, so is beyond the scope of this document.
Possible RDF Output
The following is a possible RDF/XML representation of the information in the example above.
<?xml version="1.0"?> <rdf:RDF xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xfn="http://vocab.sindice.com/xfn#" xmlns="http://www.w3.org/2006/vcard/ns#"> <!-- Alice --> <VCard rdf:nodeID="bnode01"> <!-- data from Alice's hCard --> <fn>Alice Jones</fn> <adr rdf:parseType="Resource"> <locality>Sydney</locality> <country-name>Australia</country-name> </adr> <url rdf:resource="http://alice.example.com/blog/" /> <!-- data from Alice's XFN links --> <foaf:page rdf:resource="http://alice.example.com/blog/" /> <foaf:knows rdf:nodeID="bnode02" /> <xfn:met rdf:nodeID="bnode02" /> <xfn:friend rdf:nodeID="bnode02" /> <foaf:knows rdf:nodeID="bnode03" /> <xfn:met rdf:nodeID="bnode03" /> <xfn:co-worker rdf:nodeID="bnode03" /> <foaf:knows rdf:nodeID="bnode04" /> <xfn:met rdf:nodeID="bnode04" /> <xfn:friend rdf:nodeID="bnode04" /> <xfn:neighbor rdf:nodeID="bnode04" /> <foaf:knows rdf:nodeID="bnode05" /> <xfn:met rdf:nodeID="bnode05" /> </VCard> <!-- Bob, data from hCard --> <VCard rdf:nodeID="bnode02"> <fn>Bob Smith</fn> <url rdf:resource="http://bob.example.net" /> </VCard> <!-- Carol, implied data --> <foaf:Person rdf:nodeID="bnode03"> <foaf:name>Carol Brown</foaf:name> <foaf:page rdf:resource="http://carol.example.net" /> </foaf:Person> <!-- Dave, implied data --> <foaf:Person rdf:nodeID="bnode04"> <foaf:name>Dave Wong</foaf:name> <foaf:page rdf:resource="http://dave.example.net" /> </foaf:Person> <!-- Eve, data from hCard --> <VCard rdf:nodeID="bnode05"> <fn>Eve Ville</fn> <url rdf:resource="http://eve.example.net" /> <uid>http://eve.example.net"</uid> <email rdf:resource="mailto:eve@example.net" /> </VCard> </rdf:RDF>
Note that some personal data for contacts is expressed in the FOAF vocabulary, and some information is expressed in vCard/hCard vocabulary. User agents may use OWL or another technique to draw equivalencies between vocabularies, such as taking fn
to be equivalent to foaf:name
.
Organisation hCards and XFN
If either the subject or object hCard represents an organisation (rather than a person), the following relationships are meaningless:
- acquaintance
- friend
- child
- parent
- sibling
- spouse
- kin
- crush
- date
- sweetheart
Reverse Relationships
Explicit reverse relationships may be provided by authors using the rev
attribute. These should be interpreted by parsers in exactly the same manner as described above, however subject and object must be swapped.
The XFN 1.1 profile explicitly mentions inverses for some XFN relationships, and lists which relationships are symmetric (i.e. their own inverse). For example, as Alice met Bob, it is implied that Bob met Alice. Parsers may use the information in the profile to make explicit the implicit reverse relationships.
Inspiration, References
- Re: XFN is getting smoked by FOAF — Toby Inkster, 2008-03-11
- Re: XFN + hCard — Toby Inkster, 2008-03-12
- Re: A (big) problem with XFN: identity of source and target not findable — Toby Inkster, 2008-03-18
- Re: A (big) problem with XFN: identity of source and target not findable — David Janes, 2008-03-18
- Re: A (big) problem with XFN: identity of source andtarget not findable — Toby Inkster, 2008-03-18
- Re: A (big) problem with XFN: identity of source andtarget not findable — Roger L Costello, 2008-03-20
- Re: Coding mbox_sha1sum in XFN — Toby Inkster, 2008-04-26
Related Pages
- Sindice: Expressing the XFN microformat in RDF (largely compatible with this page) — Richard Cyganiak, 2008-06-27
XFN
- XFN+hCard supporting friends lists - examples in the wild of XFN usage.
- xfn-implementations
- xfn-cheatsheet - see http://gmpg.org/xfn/join and existing-rel-values
- xfn-faq
- xfn-clarifications - should eventually be rolled into XFN info on GMPG.org.
- xfn-issues
- xfn-brainstorming
Microformats to RDF
See also:
Other
- XHTML Enemies Network - spoof of XFN. Can be easily implemented using the same algorithm.
- XHTML Professionals Network - proposed extension to XFN to deal with corporate relationships. When/if completed, will probably be implementable using the algorithm on this page.