RDF Terms
The Term
trait defines how you interact with RDF terms in Sophia.
Using terms
The first thing you usually need to know about a term is its kind (IRI, Literal...).
The kind is described by the TermKind
enum,
and available from the Term::kind
method.
use sophia::api::term::{SimpleTerm, Term, TermKind};
use TermKind::*;
let some_term: SimpleTerm = "foo".into_term();
match some_term.kind() {
Iri => { /* ... */ }
Literal => { /* ... */ }
BlankNode => { /* ... */ }
_ => { /* ... */ }
}
Alternatively, when only one kind is of interest, you can use Term::is_iri
, Term::is_literal
, Term::is_blank_node
, etc.
If you are interested in the "value" of the term, the trait provides the following methods. All of them return an Option
, which will be None
if the term does not have the corresponding kind.
-
If the term is a blank node,
Term::bnode_id
returns its blank node identifier. -
If the term is a literal:
Term::lexical_form
returns its lexical form (the "textual value" of the literal),Term::datatype
returns its datatype IRI1,Term::language_tag
returns its language tag, if any.
-
If the term is a quoted triple:
Term::triple
returns its 3 components in an array of terms,Term::constituents
iterates over all its constituents,Term::atoms
iterates over all its atomic (i.e. non quoted-triple) constituents.- (those three methods also have a
to_X
version that destructs the original term instead of borrowing it)
-
If the term is a variable2,
Term::variable
returns its name.
Finally, the method Term::eq
can be used to check whether two values implementing Term
represent the same RDF term. Note that the ==
operator may give a different result than Term::eq
on some types implementing the Term
trait.
Useful types implementing Term
Below is a list of useful types implementing the Term
trait:
Iri
<T>
andIriRef
<T>
, whereT: Borrow<str>
, representing IRIsBnodeId
<T>
, whereT: Borrow<str>
, representing blank nodesstr
, representing literals of typexsd:string
,i32
,isize
andusize
representing literals of typexsd:integer
,f64
representing literals of typexsd:double
,SimpleTerm
(see below).
SimpleTerm
is a straightforward implementation of Term
, that can represent any kind of term, and can either own its own underlying data or borrow it from something else.
Any term can be converted to a SimpleTerm
using the Term::as_simple
method.
This method borrows as much as possible from the initial term to avoid spurious memory allocation.
Alternatively, to convert any term to a self-sufficient SimpleTerm
, you can use Term::into_term
See also the list of recipes below.
Borrowing terms with Term::borrow_term
In Sophia, all functions accepting terms as parameters are expecting a type T: Term
-- not &T
, but the type T
itself. So what happens when you want to call such a function with a term t
, but still want to retain ownership of t
?
The solution is to pass t.borrow_term()
to the function. This method returns something implementing Term
, representing the same RDF term as t
, without waiving ownership. This is a very common pattern in Sophia.
More precisely, the type returned by t.borrow_term()
is the associated type Term::BorrowTerm
. In most cases, this is a reference or a copy of t
.
Recipes for constructing terms
Constructing IRIs
fn main() -> Result<(), Box<dyn std::error::Error>> {
use sophia::{iri::IriRef, api::ns::Namespace};
let some_text = "http://example.org";
// construct an IRI from a constant
let iri1 = IriRef::new_unchecked("http://example.org");
// construct an IRI from an untrusted string
let iri2 = IriRef::new(some_text)?;
// construct multiple IRIs from a namespace
let ns = Namespace::new_unchecked("http://example.org/ns#");
let iri3 = ns.get_unchecked("foo");
let iri4 = ns.get(some_text)?;
// standard namespaces
use sophia::api::ns::{rdf, xsd};
let iri5 = rdf::Property ;
let iri6 = xsd::string ;
Ok(()) }
Constructing literals
fn main() -> Result<(), Box<dyn std::error::Error>> {
use sophia::api::{ns::xsd, term::{LanguageTag, SimpleTerm, Term}};
// use native types for xsd::string, xsd::integer, xsd::double
let lit_string = "hello world";
let lit_integer = 42;
let lit_double = 1.23;
// construct a language-tagged string
let fr = LanguageTag::new_unchecked("fr");
let lit_fr = "Bonjour le monde" * fr;
// construct a literal with an arbitrary datatype
let lit_date = "2023-11-15" * xsd::date;
Ok(()) }
Constructing blank nodes
fn main() -> Result<(), Box<dyn std::error::Error>> {
use sophia::api::term::BnodeId;
let b = BnodeId::new_unchecked("x");
Ok(()) }
Converting terms into a different type
use sophia::api::{ns::xsd, term::{SimpleTerm, Term}};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let some_term = "42" * xsd::integer;
let t1: SimpleTerm = "hello".into_term();
let t2: i32 = some_term.try_into_term()?;
Ok(()) }
Note that in Sophia's generalized RDF model, IRIs can be relative IRI reference.
Note that this kind only exist in Sophia's generalized RDF model.