RDF/POST is a syntax for encoding an RDF graph as HTTP GET URL query string or POST form-urlencoded request body. It can be used for building RDF editing interfaces with plain HTML forms (no JavaScript required).
This document is based on the original RDF/POST draft by Sergei Egorov.
The Resource Description Framework (RDF) is the basic knowledge representation model for the W3C Semantic Web initiative. RDF/POST is an encoding method allowing the transfer of RDF data via the traditional HTTP GET and HTTP POST mechanism, facilitating the creation of RDF-in/RDF-out web services with dual interfaces (direct programmatic access and human-friendly entry and result pages).
The W3C HTML 4 Forms recommendation specifies the behavior of HTTP user agents and includes a short description of the format used for submission of form data (MIME type "application/x-www-form-urlencoded"). The format is rather simple; its data model is an ordered list of key/value pairs, where keys and values are just strings. As implemented in modern browsers, the format has its limitations, but there is nothing preventing one from using (a profile of) it to serialize any RDF graph.
The proposed serialization is straightforward and rather concise, which makes it suitable for use with HTTP GET (URLs over 2K in length run a risk of causing 414 Request URL Too Long reply from the server). It inherits the abbreviated tree form from [[Turtle]], using different keys for subject, predicate, and object to eliminate the need for punctuation.
This EBNF is defined in XML 1.0 second edition [[XML]].
rdf | ::= | 'rdf= ' def_ns_decl? ns_decl* triples* |
def_ns_decl | ::= | '&v= ' uri_prefix |
ns_decl | ::= | '&n= ' name '&v= ' uri_prefix |
triples | ::= | subj property* |
subj | ::= | blank_subj | uri_subj | def_ns_subj | ns_subj |
blank_subj | ::= | '&sb= ' name |
uri_subj | ::= | '&su= ' uri |
def_ns_subj | ::= | '&sv= ' uri_suffix |
ns_subj | ::= | '&sn= ' name '&sv= ' uri_suffix |
property | ::= | pred obj* |
pred | ::= | uri_pred | def_ns_pred | ns_pred |
uri_pred | ::= | '&pu= ' uri |
def_ns_pred | ::= | '&pv= ' uri_suffix |
ns_pred | ::= | '&pn= ' name '&pv= ' uri_suffix |
obj | ::= | blank_obj | uri_obj | def_ns_obj | ns_obj | literal_obj |
blank_obj | ::= | '&ob= ' name |
uri_obj | ::= | '&ou= ' uri |
def_ns_obj | ::= | '&ov= ' uri_suffix |
ns_obj | ::= | '&on= ' name '&ov= ' uri_suffix |
literal_obj | ::= | '&ol= ' string type_or_lang? | type_or_lang '&ol= ' string |
type_or_lang | ::= | type | lang |
type | ::= | '<= ' uri |
lang | ::= | '&ll= ' lang_id |
uri | ::= | string /* URI as defined in RFC3986 */ |
uri_prefix | ::= | uri /* any valid URI prefix */ |
uri_suffix | ::= | uri /* any valid URI suffix */ |
lang_id | ::= | string /* see xml:lang */ |
name | ::= | [A -Za -z ][A -Za -z0 -9 ]* /* same as in N-Triples */ |
string | ::= | (schar | plus | echar)* /* unreserved or urlencoded */ |
schar | ::= | [A -Za -z0 -9.,;:'/?!$@()*~_- ] /* safe as per RFC3986 */ |
plus | ::= | '+ ' /* encodes single space (#x20) */ |
echar | ::= | '% '[0 -9A -Fa -f ][0 -9A -Fa -f ] /* encodes one octet */ |
The use of this format in HTML pages relies on the fields are listed in the order they appear
requirement of the HTML Forms specification. Since HTML user agents are not required to send fields with null values (browsers are free to ignore them), such fields should not be used to send pairs which are important for correct decoding of the format (e.g. a pair defining the subject of a triple). Remember that hidden fields are always sent if they have value
attributes present.
To handle data submitted from HTML forms, the decoder should allow for some missing pairs, skipping to the next sync point (if any) and silently ignoring the affected triples:
&pv=
, &pn=
, or &pu=
ahead: skip to the
next subj (&sb=
, &su=
, &sv=
, &sn=
).&pn=
name is seen, but there's no &pv=
ahead: skip to the next subj
(&sb=
, &su=
, &sv=
, &sn=
).&ob=
, &ov=
, &on=
, &ou=
, or &ol=
ahead:
skip to the next pred (&pu=
, &pv=
, or &pn=
) or subj
(&sb=
, &su=
, &sv=
, &sn=
),
whichever comes first.&on=
name is seen, but there's no &ov=
ahead: skip to the next pred
(&pu=
, &pv=
, or &pn=
) or subj (&sb=
, &su=
, &sv=
, &sn=
),
whichever comes first.<=
or &ll=
is seen, but there is no &ol=
ahead: skip to the next non-literal obj (&ob=
, &ou=
, &ov=
, or &on=
), pred (&pu=
, &pv=
, or &pn=
) or subj (&sb=
, &su=
, &sv=
, &sn=
), whichever comes first.Strings can contain any Unicode character encoded in UTF-8 and, if the resulting octets fall outside of US_ASCII, urlencoded as described in Form content types - application/x-www-form-urlencoded [[HTML401]]. The simplest way to ensure that browsers send form data in UTF-8 is to encode form pages in UTF-8.
Here is a simple RDF/POST document encoded in a simple HTML form:
The HTML code of this form looks like this:
<form>
<p>
<input type="hidden" name="rdf" value=""/>
<!-- namespace declarations -->
<input type="hidden" name="v" value="http://xmlns.com/foaf/0.1/"/>
<input type="hidden" name="n" value="rdf"/>
<input type="hidden" name="v" value="http://www.w3.org/1999/02/22-rdf-syntax-ns#"/>
<input type="hidden" name="n" value="dc"/>
<input type="hidden" name="v" value="http://purl.org/dc/elements/1.1/"/>
<!-- triples -->
<span>Someone called</span>
<input type="hidden" name="sb" value="o"/>
<input type="hidden" name="pv" value="givenName"/>
<input type="text" name="ol" value="Ora" size="10"/>
<input type="hidden" name="pv" value="familyName"/>
<input type="text" name="ol" value="Lasilla" size="10"/>
<input type="hidden" name="pn" value="dc"/>
<input type="hidden" name="pv" value="creator"/>
<input type="hidden" name="ob" value="b"/>
<input type="hidden" name="sb" value="b"/>
<input type="hidden" name="pn" value="rdf"/>
<input type="hidden" name="pv" value="type"/>
<select name="ov">
<option selected="selected" value="Document">wrote a book</option>
<option value="Image">painted a picture</option>
</select>
<span>titled</span>
<input type="hidden" name="pn" value="dc"/>
<input type="hidden" name="pv" value="title"/>
<input type="text" name="ol" value="Moby Dick" size="20"/>
<button type="submit">Post</button>
</p>
</form>
During form submission, the browser constructs the following query string (spaces and indentation are added for presentation purposes):
rdf=
&v=http://xmlns.com/foaf/0.1/
&n=rdf &v=http://www.w3.org/1999/02/22-rdf-syntax-ns%23
&n=dc &v=http://purl.org/dc/elements/1.1/
&sb=o
&pv=givenName
&ol=Ora
&pv=familyName
&ol=Lasilla
&pn=dc &pv=creator
&ob=b
&sb=b
&pn=rdf &pv=type
&ov=Document
&pn=dc &pv=title
&ol=Moby+Dick
It can be compared line-by-line with the equivalent Turtle description:
@prefix : <http://xmlns.com/foaf/0.1/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns%23> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
_:o
:givenName
"Ora" ;
:familyName
"Lasilla" ;
dc:creator
_:b .
_:b
rdf:type
:Document ;
dc:title
"Moby Dick" .
If one wants to make sure that submitted data conforms to RDF datatype requirements, e.g. does not contain unexpected empty string values and incorrectly formatted dates, the forms can be validated with Javascript code.
As a rule, RDF/POST data is sent with "application/x-www-form-urlencoded" media type; if one needs to distinguish RDF/POSTs from regular posts, a more specific "application/rdf+x-www-form-urlencoded" media type can be used (not yet registered with IANA). Encoding considerations are the same in both cases; RDF/POSTs can be distinguished by the rdf=
prefix.
Recommended file extension is ".rpo"