xfn-to-foaf: Difference between revisions

From Microformats Wiki
Jump to navigation Jump to search
(Minor updates, wiki-2-ification.)
m (Replace <entry-title> with {{DISPLAYTITLE:}})
 
(4 intermediate revisions by one other user not shown)
Line 1: Line 1:
<entry-title>XFN &rarr; FOAF</entry-title>
{{DISPLAYTITLE:XFN FOAF}}
{{TOC-right}}
{{TOC-right}}
by [[User:TobyInk|Toby Inkster]]
by [[User:TobyInk|Toby Inkster]]
Line 23: 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 &lt;http://alice.example.net&gt;.</nowiki></pre>
         foaf:page &lt;http://alice.example.net&gt;.</nowiki></pre>


Line 50: Line 50:
# 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:  
# 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;
<pre><nowiki>_:bnode02 a foaf:Person;
         foaf:page &lt;http://bob.example.net&gt;;
         foaf:page &lt;http://bob.example.net&gt;;
         foaf:name "Bob Smith".</nowiki></pre>
         foaf:name "Bob Smith".</nowiki></pre>
Line 133: 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://vocab.sindice.com/xfn#"
         xmlns:xfn="http://vocab.sindice.com/xfn#"
         xmlns:hcard="urn:ietf:rfc:2426#">
         xmlns="http://www.w3.org/2006/vcard/ns#">


   <!-- Alice -->
   <!-- Alice -->
   <Person rdf:nodeID="bnode01">
   <VCard rdf:nodeID="bnode01">
    
    
     <!-- data from Alice's hCard -->
     <!-- data from Alice's hCard -->
     <hcard:fn>Alice Jones</hcard:fn>
     <fn>Alice Jones</fn>
     <hcard:adr>
     <adr rdf:parseType="Resource">
       <hcard:locality>Sydney</hcard:locality>
       <locality>Sydney</locality>
       <hcard:country-name>Australia</hcard:country-name>
       <country-name>Australia</country-name>
     </hcard:adr>
     </adr>
     <hcard:url rdf:resource="http://alice.example.com/blog/" />
     <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" />
      
      
   </Person>
   </VCard>
    
    
   <!-- Bob, data from hCard -->
   <!-- Bob, data from hCard -->
   <Person rdf:nodeID="bnode02">
   <VCard rdf:nodeID="bnode02">
     <hcard:fn>Bob Smith</hcard:fn>
     <fn>Bob Smith</fn>
     <hcard:url rdf:resource="http://bob.example.net" />
     <url rdf:resource="http://bob.example.net" />
   </Person>
   </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 -->
   <Person rdf:nodeID="bnode05">
   <VCard rdf:nodeID="bnode05">
     <hcard:fn>Eve Ville</hcard:fn>
     <fn>Eve Ville</fn>
     <hcard:url rdf:resource="http://eve.example.net" />
     <url rdf:resource="http://eve.example.net" />
     <hcard:uid rdf:resource="http://eve.example.net" />
     <uid>http://eve.example.net"</uid>
     <hcard:email rdf:resource="mailto:eve@example.net" />
     <email rdf:resource="mailto:eve@example.net" />
   </Person>
   </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>hcard:fn</code> to be equivalent to <code>foaf:name</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 ==

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

  1. Find the representative hCard for the current page.
  2. 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.)
  3. 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

  1. 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.
  2. 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.)
  3. If no hCard representing the object of the relationship has been found, then the object is taken to be a foaf:Person with a foaf:name corresponding to the link text and, depending on the kind of link provided in the href attribute, a foaf:mbox (for "mailto:" links), foaf:mbox_sha1sum (for "urn:sha1:" URLs), foaf:img (image links, determined by type attribute or HTTP headers, not by file name) or foaf: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 &amp; 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

Related Pages

XFN

Microformats to RDF

See also:

Other