OUT-OF-DATE DRAFT (DO NOT USE) This has been incorporated into the OSLCCoreSpecDRAFT
The OSLC Core Specification provides a means for describing resources using RDF data model concepts (e.g. resources, properties, literal values, statements, triples, graphs, etc.). This document defines the semantics for queries written using the OSLC Core Simple Query Syntax V1 in terms of the RDF data model.
The semantics are illustrated here using simple examples. The formal semantics are given by translating the simple query syntax into SPARQL. See OSLC Simple Query SPARQL Semantics V1 for details.
This document assumes that resource types are described using RDF concepts. The following paragraphs give a very brief description of the RDF data model concepts used in this document.
In RDF terms, resources are identified either by URIs, or blank nodes. Blank nodes may be compared to each other for equality, but their actual values are irrelevant. When blank nodes are represented in a document, they are given values that are local to the document (e.g. using the rdf:nodeID attribute in RDF/XML documents). In general, any given resource may have many identifiers (both URIs and blank nodes), however, every resource identifier MUST identify a unique resource.
A resource, whose identifier is S
, is described by a set of statements (a.k.a. triples
) of the form (S,P,O)
where, P
is the URI of some property, and O
is either a literal value (e.g. a number, string, or XML fragment) or the identifier of some resource. In the triple (S,P,O)
, S is the subject, P is the predicate, and O is the object. Each statement describes either an attribute of S
if O
is a literal value, or a relation between S
and O
if O
identifies a resource. In general, triples with a given property P
may occur zero or more times for a given resource S
.
A property that may occur more than once for a given subject is called a multi-valued property. Some multi-valued properties may be used define the notion of membership of the object resources in the subject resource, which is sometimes refered to as a container.
A set of RDF statements may be viewed as defining a graph (technically, a directed, labeled graph). The graph is constructed by taking the set of all the subjects and objects that appear in statements as the nodes of the graph, and, for each statement, adding an arc from the subject to the object. Label the nodes with their resource identifier or literal value. Label the arcs by the URI of the predicate.
A set of RDF statements may be stored in a specialized data base referred to as a triple store. A triple store (e.g. Jena) typically supports queries (e.g. written in SPARQL), and parsing and generation of representations of sets of triples in RDF formats such as RDF/XML, N3, and Turtle.
The simple query syntax described here has a natural interpretation in terms of matching graph patterns.
The simplest graph pattern is a single RDF triple. This pattern matches a graph if the triple is contained in the graph.
We can create more complex graph patterns by considering sets of the triples. A set of triples matches a graph is each triple is contained in the graph, i.e. they define a subgraph of the graph.
We can further generalize these graph patterns by including triple templates. A triple template is like a triple except that in addition to URIs, blank nodes, and literal values, the triples may als contain named variables as the subject, predicate, or object. Any given named variable may occur in multiple places within a triple and within mutliple triples. A match for such a graph pattern is an assignment of URIs, blank nodes, or literal values to the named variables such that when these are substituted in the graph pattern, the resulting set of triples is a subgraph.
A query URL may be formed by appending a set of query parameters to a given URL which we refer to as the base URL. The query result is normally requested by sending an HTTP GET request to the query URL.
However, if the query parameters are very long, it may be preferable to instead request the result of the query by sending an HTTP POST request to the base URL and include the query parameters in the HTTP request body as content with media type application/x-www-form-urlencoded
. In REST parlance, this is sometimes refered to as an overloaded POST. In the following sections we'll normally talk about appending query parameters to the base URL to form a query URL, and sending an HTTP GET request to the query URL with the understanding that similar statements apply to the HTTP POST case.
In either the GET or POST case, the base URL provides the context for the query. This specification describes two main types of base URL which we'll refer to as self-subject and multi-subject. Refer to the OLSC Core Specification section on Query Capabilities for how to identify and describe base URLs.
A self-subject base URL is simply any subject resource node in the graph. Any such base URL SHOULD respond to an HTTP GET request by returning some representation of the resource. The query parameters defined here let you modify that representation in various ways. The base URL defines the starting subject node for matching the graph patterns defined by the query parameters.
When computing the query response, the service MUST first perform a normal existence check on the base URL. If the base URL does not exist, then the service MUST return a suitable HTTP error code, e.g. 404 Not Found. If the base URL exists then the service should proceed to generate the query response.
The query response contains triples that provide information about this single starting subject resource and therefore its RDF/XML representation SHOULD begin with the same document element as the response for the base URL, i.e. a node element like rdf:Description or one with type information. Note that the starting subject node type information MAY be added by the service independently of the result of the graph pattern, i.e. the graph pattern MAY not explicity contain the rdf:type property.
A multi-subject base URL defines some set of starting subject nodes. For example, the base URL might represent the set of all subject nodes in the graph, or it might represent some smaller subset of root container resources. How multi-subject base URLs are used depends on the service specification.
The response for a multi-subject query URL is the union of the responses for the single-subject query URLs formed for each resource in the set of starting subject nodes.
Since the query response MAY contain information about zero or starting subject nodes, its RDF/XML representation MUST begin with the rdf:RDF document element and contain child elements for the starting subject nodes that are in the query response. Note that as in the case of single-subject base URLs, the service MAY add type information in the child elements independently of the graph pattern.
The query parameters described in this specification combine to define a full graph pattern that is matched against an RDF graph. As described above, the base URL of the request defines one or more starting subject nodes for the matches. The query response for the full graph pattern is the union of all the matches for all the starting nodes.
The full graph pattern is itself composed of two parts which we refer to as the property tree pattern and the member list pattern. The query response for the full graph pattern is the union of the query response for the property tree pattern and the query response for the member list pattern. The representation of the full graph pattern query response SHOULD contain the triples from the property tree pattern query response followed by the triples from the member list pattern query response.
Specifically, if one or more of the following query parameters are present in the request, then a full query pattern is defined and this specification applies:
oslc.properties
oslc.from, oslc.where
, oslc.searchTerms
, oslc.orderBy
, oslc.offset
, oslc.limit
, oslc.select
If none of the above query parameters are present then a full graph pattern is NOT defined and the service MUST handle the request by returning its defined response for the base URL and any other query parameters that may be present. In the absence of a full graph pattern, the service SHOULD include the most significant properties. The service MAY omit properties that are for bookkeeping, e.g. last modified date, ETag, etc. since including them in all responses may simply increase reduce performance with no other application benefits.
When a property tree pattern is used in combination with a member list pattern then oslc.properties
SHOULD NOT include properties that are specified by oslc.from
, either explicitly or by default, since this will normally result in triples that match both patterns. In this case a service MAY include duplicate triples in the response.
Similarly, when oslc.from
specifies more than one property, a resource in the member list may match more than one triple. The relative order of these triples for a given resource is undefined.
Note that the above list does NOT include the oslc.prefix
query parameter which MAY be present but does NOT itself contribute to any pattern. Instead, it is used to define URI prefixes that MAY be used in the other query parameters.
The property tree pattern lets you request specific properties of a starting subject resource, including specific properties of resources referenced by the starting resource, and so on recursively, forming a tree of properties.
The property tree pattern of a full graph pattern is defined by the oslc.properties
query parameter. If the oslc.properties
query parameter is not present then the property tree pattern is empty and it contributes no triples to the query response.
The oslc.properties
query parameter defines a tree of property arcs. Each property arc is either the prefixed name of a property or a wildcard (*). The wildcard denotes any property.
The property tree pattern consists of a list one or more base property arcs. Each base property MAY be followed a list of one of more nested property arcs enclosed in brace brackets. Each nested property arc MAY be followed by its own list of one or more nested property arcs, and so on recursively. The property arc that contains a nested property arc is called its parent property arc.
A predicate P
matches a property arc if either the arc is a wildcard, or the arc has a prefixed name equal to P.
A triple (S, P, O)
matches a base property arc if P
matches the base property arc and S
is a starting subject node.
A triple (S, P, O)
matches a nested property arc if P
matches the nested property arc and S
is the object of some triple that matches the parent property arc.
The query result is the union of all the triples that match some property arc.
Any property of a resource can be requested using the property tree pattern described above. However, in practice some mutli-valued properties may have a very large number of occurances, so it is often useful to request a subset of them. For example, a resource may be a container for other resources, refered to its members. For example, a bug tracking service might have a container resource whose members are the bug reports. It is common for bug tracking systems to manage hundreds of thousands of bug reports.
The member list pattern lets you request a subset of the occurances of one of more properties. In practice, these properties are often container membership properties, hence the use of "member" in the name of this pattern. However, this pattern can be used with any properties, not just membership properties. Furthermore, this pattern lets you optionally order the members, hence the use of "list" in the name of this pattern.
The member list pattern of a full graph pattern is defined by the following query parameters: oslc.from, oslc.where
, oslc.searchTerms
, oslc.orderBy, oslc.limit, oslc.offset
, oslc.select
If none of these query parameters are present in the request then the member list pattern is empty and it contributies no triples to the query result. The query response is defined by a sequence of steps as described below.
The semantics of this pattern is defined by a pipeline of operations. The output of an operation becomes the input to the next one in the pipeline. Each operation refers to of the query parameters. If the query parameter is absent then the operation has a well-defined default behavior.
The state of the pipeline is defined by the pair (T, V) where T is a set of triples and V is an ordered list (aka vector) of object nodes that represent the member resources, i.e. V is the member list. The query result is the set of triples T returned in the order defined by V.
The pipeline has the following operations:
oslc.from
. Initialize V to be the set of all object nodes that appear in the triples of T, listed in some unspecified, but repeatable, order.
oslc.where
. Remove the corresponding triples from T.
oslc.searchTerms
. Sort V in descending order of score.
oslc.orderBy
.
oslc.offset
. If M >= N then discard all objects in V. Otherwise M < N so discard the first M objects. Discard the corresponding triples from T.
oslc.limit
. If N > M then discard the last N - M objects from V so that now at most M objects now remain in V. Discard the corresponding triples from T.
oslc.select
using the object nodes in V as the starting subject nodes.
The oslc.from
query parameter specifies a list of one or more properties whose objects we view as members of some subject container resource, i.e. they define the initial member list. In practice, oslc.from
will specify one or more membership properties. However, any properties MAY be specified, i.e. they do NOT have to be membership properties.
If this query parameter is absent then the service MUST provide a, possibly empty, default value. A service SHOULD provide a default value that is consistent with the service description specified by the OSLC Core specification, namely that the default value is the list of all properties associated with the base URL that are defined using the oslc:memberProperty
property.
The oslc.where
query parameter defines a list of one or more boolean conditions that filter the member list. Each condition is a graph pattern that resources in the member list MUST satisify.
Note that since, in general, properties are multi-valued, each condition is satisified if some triple satisfies it. For example, suppose that bug resources have a multi-valued ex:subscriber property. Consider the following query:
http://example.com/bugs?oslc:where=ex:subscriber="John"
The query result contains any bug that John subscribes to, i.e. any given bug returned in the query result may have additional subscribers other than John.
If oslc.where
is not present, then its default value is the boolean value true
and the member list MUST NOT change.
The oslc.searchTerms
query parameter provides a list of search terms that a full text search engine applies to each resource in the member list, and assigns it a score. The details of the full text search are implementation-dependent. The member list MUST be sorted by score in descending order, i.e. best score first. This sort SHOULD be a stable sort, i.e. it SHOULD NOT change the relative order of resources that have the same score.
If this parameter is absent, then each resource in the member list is assigned a score of 0 and the order of the member list MUST NOT change.
The oslc.orderBy
query parameter provides a list of sort keys. Each sort key SHOULD specify a property of the resources in the member list. Each sort key also defines a sort direction. The resources in the member list are sorted by these sort keys, preserving the full text search score as the implicit primary sort key. The sort SHOULD be stable, i.e. the sort SHOULD NOT change the relative order of resources that have the same values for all the sort keys.
The sort keys SHOULD be required and single-valued. The sorting behavior is undefined otherwise.
If this query parameter is absent then the default value is the empty list of sort keys and the order of the member list MUST NOT change.
The oslc.offset
query parameter specifies an offset into the member list, i.e. it specifies the number of resources to discard from the start of the member list. If the offset is M then up to an including the first M resources of the member list are discarded.
An offset of 0 specifies the the full member list.
If this query parameter is absent, its default value is 0 and the member list MUST NOT change.
The oslc.offset
query parameter specifies the size limit of the member list. If the limit is M then up to an including the first M resources in the member list are kept and the rest are discarded.
If this query parameter is absent, its default value is effectively infinity and the member list MUST NOT change.
The semantics of the oslc.select
query parameter are the same as for the oslc.properties
query parameter except that its graph matching pattern is applied to each resource in the member list.
If this query parameter is not present, then the service SHOULD NOT include any properties (including rdf:type) of the resources in the member list.
The following sections give examples of the query syntax.
The OSLC Core specification describes the recommended way to represent a resource using RDF/XML. In general, there are many equivalent ways to encode a set of RDF triples for a resource s as RDF/XML. The OSLC Core specifies that the representation omit the enclosing rdf:RDF element and instead have a document root that describes the type of the resource. The body of the document consists of a flat list of the properties of the the resource. For example, the following is an RDF/XML representation of the ems:Project resource whose URL is http://braintwistors.example.com/ems10/Project/4201:
<ems:Project xmlns:dcterms="http://purl.org/dc/terms/" xmlns:ems="http://open-services.net/software-metrics/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" rdf:about="http://braintwistors.example.com/ems10/Project/4201"> <dcterms:title>Tsunami 1.0</dcterms:title> <dcterms:description> The goal of this project is to create a web version of Tsunami, a Japanese logic puzzle, in order to drive traffic to the BrainTwistors Corp. website and increase advertising revenue. Future plans include developing free iPhone, BlackBerry, and Nintendo DS versions, and charging for puzzle downloads. </dcterms:description> <dcterms:identifier>4201</dcterms:identifier> <ems:projectList rdf:resource="http://braintwistors.example.com/ems10/Project" /> <!-- other properties of this Project resource have been omitted for brevity --> </ems:Project>
In terms of RDF triples, this resource has the following data:
Subject | Predicate | Object |
---|---|---|
<http://braintwistors.example.com/ems10/Project/4201> | rdf:type | ems:Project |
<http://braintwistors.example.com/ems10/Project/4201> | dcterms:title | "Tsunami 1.0" |
<http://braintwistors.example.com/ems10/Project/4201> | dcterms:description | "The goal of this project is ..." |
<http://braintwistors.example.com/ems10/Project/4201> | dcterms:identifier | "4201" |
<http://braintwistors.example.com/ems10/Project/4201> | ems:projectList | <http://braintwistors.example.com/ems10/Project> |
... | ... | ... |
The query syntax includes the capability to specify a subset of properties to be included in the representation. The set of desired properties is specified in a comma-separated list of, possible nested, property names given as the value of the oslc.properties
query parameter. For example, the query URI:
http://braintwistors.example.com/ems10/Project/4201?oslc.properties=dcterms:title,ems:projectList
selects the properties dcterms:title and ems:projectList. The oslc.properties
query parameter defines the following graph pattern, where a match is defined as a set of variable substitutions for the variables ?v1 and ?v2 which correspond the the properties dcterms:title and ems:projectList that result in a set of triples that are contained in the full RDF graph:
Subject | Predicate | Object |
---|---|---|
<http://braintwistors.example.com/ems10/Project/4201> | dcterms:title | ?v1 |
<http://braintwistors.example.com/ems10/Project/4201> | ems:projectList | ?v2 |
There is only one variable substitution that matches the graph pattern:
?v1 | ?v2 |
---|---|
"Tsunami 1.0" | <http://braintwistors.example.com/ems10/Project> |
This results in the following subgraph:
Subject | Predicate | Object |
---|---|---|
<http://braintwistors.example.com/ems10/Project/4201> | dcterms:title | "Tsunami 1.0" |
<http://braintwistors.example.com/ems10/Project/4201> | ems:projectList | <http://braintwistors.example.com/ems10/Project> |
The matched subgraph has the following RDF/XML representation:
<ems:Project xmlns:dcterms="http://purl.org/dc/terms/" xmlns:ems="http://open-services.net/software-metrics/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" rdf:about="http://braintwistors.example.com/ems10/Project/4201"> <dcterms:title>Tsunami 1.0</dcterms:title> <ems:projectList rdf:resource="http://braintwistors.example.com/ems10/Project" /> </ems:Project>
Note that the value of the rdf:about attribute is the URI of the subject resource, Project 4201, since the query result contains statements about that subject resource. The result is RDF/XML and is intepretted as a set of triples. The value of the rdf:about attribute gives the subject node of a set of triples built from the properties dcterms:title, ems:projectList, etc. A consumer of the service may combine these triples with other triples that contain information about Project 4201, so it is important that the rdf:about attribute specify the URI of Project 4201.
The property names, e.g. dcterms:title, ems:projectList, include prefixes, e.g. dc, ems, which are either well-known prefixes that are predefined by the service or are explicitly defined using query parameters the URI. A mechanism for describing the predefined prefixes may be included in the OSLC Reporting specification. The syntax for defining prefixes on the URI is specified in Property Name Prefixes. The proposed design is, e.g:
oslc.prefix=dcterms=<http://purl.org/dc/elements/1.1/>
This is added to the URI as follows:
http://braintwistors.example.com/ems10/Project/4201?oslc:prefix=dcterms=<http://purl.org/dc/elements/1.1/> &oslc.properties=dcterms:title,ems:projectList
Some resource may contain collections of other resources. The recommended way to represent such collections is to use a multi-valued property that indicates membership in the collection. The specific name of the membership property depends on the collection type.
In collection resources, the membership properties can be treated differently than the other properties via oslc.from
, oslc.where
, oslc.select
etc. The oslc.properties
query parameter should be used only to select the non-member properties.
For example, resources of type ems:ProjectList contain collections of ems:Project resources using ems:memberProject as the membership property. The following is an RDF/XML representation of an ems:ProjectList resource http://braintwistors.example.com/ems10/Project:
<ems:ProjectList xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:ems="http://open-services.net/software-metrics/" rdf:about="http://braintwistors.example.com/ems10/Project"> <dcterms:title>BrainTwistors Corp. Project List</dcterms:title> <dcterms:description> This is the list of all Project resources contained in BrainTwistors Corp. MetricServer web application. </dcterms:description> <ems:service rdf:resource="http://braintwistors.example.com/ems10" /> <ems:memberProject rdf:resource="http://braintwistors.example.com/ems10/Project/2009" /> <ems:memberProject rdf:resource="http://braintwistors.example.com/ems10/Project/3707" /> <ems:memberProject rdf:resource="http://braintwistors.example.com/ems10/Project/3998" /> <!-- Other members of this ProjectList resource have been omitted for brevity. --> </ems:ProjectList>
The RDF graph contains the followiing triples:
Subject | Predicate | Object |
---|---|---|
<http://braintwistors.example.com/ems10/Project> | ems:memberProject | <http://braintwistors.example.com/ems10/Project/2009> |
<http://braintwistors.example.com/ems10/Project> | ems:memberProject | <http://braintwistors.example.com/ems10/Project/3707> |
<http://braintwistors.example.com/ems10/Project> | ems:memberProject | <http://braintwistors.example.com/ems10/Project/3998> |
<http://braintwistors.example.com/ems10/Project/2009> | dcterms:identifier | "2009" |
<http://braintwistors.example.com/ems10/Project/3707> | dcterms:identifier | "3707" |
<http://braintwistors.example.com/ems10/Project/3998> | dcterms:identifier | "3998" |
... | ... | ... |
oslc.where
query parameter. (This query parameter is called oslc.where
since it is like the SQL WHERE clause.)
For example, the following URI filters the ems:ProjectList collection to just contain the ems:Project whose dcterms:identifier is 2009:
http://braintwistors.example.com/ems10/Project?oslc.where=dcterms:identifier="2009"
The oslc.where
query parameter defines the following graph pattern which filters the set of resources that belong to the result set. The variable ?result is used below to designate resources that belong to the result set:
Subject | Predicate | Object |
---|---|---|
<http://braintwistors.example.com/ems10/Project> | ems:memberProject | ?result |
?result | dcterms:identifier | "2009" |
There is only one match:
?result |
---|
<http://braintwistors.example.com/ems10/Project/2009> |
The RDF/XML representation of this filtered collection is:
<ems:ProjectList xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:ems="http://open-services.net/software-metrics/" rdf:about="http://braintwistors.example.com/ems10/Project"> <ems:memberProject rdf:resource="http://braintwistors.example.com/ems10/Project/2009" /> </ems:ProjectList>
The above discussion assumes that the author of the query knows which resources are collections and which properties of those resources are membership properties. The service must specify that information by some mechanism. The OSLC Core specification defines a mechanism for describing these aspects of a service.
Although we do not require that a service provide an RDFS description of its vocabulary, RDFS does provide a mechanism for describing collections and membership properties. The RDFS class rdfs:Container is the superclass of all RDFS container classes. The RDFS class rdfs:ContainerMembershipProperty is the superclass of all container membership properties.
In the above example, RDFS description would state that ems:ProjectList is a subclass of rdfs:Container and ems:memberProject is an instance of rdfs:ContainerMembershipProperty (and therefore a subproperty of rdfs:member).
Although our RDF view of resources is that they are flat lists of properties, some properties are relations, and it is useful to regard the properties of object resources as nested properties of the subject resource. Furthermore, this nesting can be extended recursively to properties of resources related to the object resource, etc. The query syntax allows you to specify nested properties by enclosing them in brace brackets, e.g. {dcterms:title}, and appending them to the parent property, e.g. ems:service{dcterms:title}.
For example, the ems:ProjectList resource is related via the predicate ems:service to the ems:Service resource whose URI is:
http://braintwistors.example.com/ems10
This ems:Service resource has the RDF/XML representation:
<ems:Service xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:ems="http://open-services.net/software-metrics/" rdf:about="http://braintwistors.example.com/ems10"> <dcterms:title>BrainTwistors Corp. MetricServer</dcterms:title> <dcterms:description> This service implements the OSLC Estimation and Measurement Service (EMS) 1.0 specification at BrainTwistors Corp. </dcterms:description> <ems:estimateList rdf:resource="http://braintwistors.example.com/ems10/Estimate" /> <ems:projectList rdf:resource="http://braintwistors.example.com/ems10/Project" /> <ems:scenarioList rdf:resource="http://braintwistors.example.com/ems10/Scenario" /> <!-- Other properties of this Service resource have been omitted for brevity. --> </ems:Service>
We can therefore select the dcterms:title property of the ems:Service resource in the representation of the ems:ProjectList resource using the following URI:
http://braintwistors.example.com/ems10/Project?oslc.properties=ems:service{dcterms:title}
Its RDF/XML representation is as follows:
<ems:ProjectList xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:ems="http://open-services.net/software-metrics/" rdf:about="http://braintwistors.example.com/ems10/Project> <ems:service> <ems:Service rdf:about="http://braintwistors.example.com/ems10"> <dcterms:title>BrainTwistors Corp. MetricServer</dcterms:title> </ems:Service> </ems:service> </ems:ProjectList>
In general, a nested property is specified by a sequence of property names, of which all but the last MUST be relations between resources. The last property name is a sequence may be either a relation or an attribute. The RDF/XML representation of the nested property consists of the usual striped XML pattern where the elements alternate between nodes and arcs in the RDF graph.
Just as it is useful to select properties of a resource to be included in a representation of the resource, it is also useful to select properties of members of a collection resource to be included in the representation of the collection, whether or not the collection is filtered. We use the query parameter oslc.select
for this purpose. (We are use the name oslc.select
since it is like the SQL SELECT clause). The syntax of its values is the same as the syntax of the oslc.properties
query parameter, however the property names are properties of the members of the collection, and not properties of the collection resource itself.
For example, the following URI selects the dcterms:identifier property of the ems:Project members of the ems:ProjectList resource:
http://braintwistors.example.com/ems10/Project?oslc.select=dcterms:identifier
The RDF/XML representation of this collection with inlined member properties is:
<ems:ProjectList xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:ems="http://open-services.net/software-metrics/" rdf:about="http://braintwistors.example.com/ems10/Project"> <ems:memberProject> <ems:Project rdf:about="http://braintwistors.example.com/ems10/Project/2009"> <dcterms:identifier>2009</dcterms:identifier> </ems:Project> </ems:memberProject> <ems:memberProject> <ems:Project rdf:about="http://braintwistors.example.com/ems10/Project/3707"> <dcterms:identifier>3707</dcterms:identifier> </ems:Project> </ems:memberProject> <ems:memberProject> <ems:Project rdf:about="http://braintwistors.example.com/ems10/Project/3998"> <dcterms:identifier>3998</dcterms:identifier> </ems:Project> </ems:project> <!-- Other members of this ProjectList resource have been omitted for brevity. --> </ems:ProjectList>
Add your comments here: