POWDER: Testing with SPARQL Queries

I've been playing around with SPARQL queries against the kind of sample data we've been looking at. The aim bring to come up with a set of queries that we can publish alongside some sample data to show how to process a DR.

This document is, in true maths exam style, an attempt to "show my working." For those who prefer to skip to the proposed answer, see the summary.

The data file used in all these examples is at http://www.fosi.org/projects/powder/multiple_examples.rdf

Let's just check it's working with this.

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?DR
WHERE {
  ?DR rdf:type wdr:WDR
}

Gives a list of the 6 DRs in the RDF instance thus:

Count DR
1 http://www.fosi.org/projects/powder/multiple_examples.rdf#DR6
2 http://www.fosi.org/projects/powder/multiple_examples.rdf#DR5
3 http://www.fosi.org/projects/powder/multiple_examples.rdf#DR4
4 http://www.fosi.org/projects/powder/multiple_examples.rdf#DR3
5 http://www.fosi.org/projects/powder/multiple_examples.rdf#DR2
6 http://www.fosi.org/projects/powder/multiple_examples.rdf#DR1

We can find out a lot by running a simple query to find all the predicates and objects for a DR thus:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?p ?o
WHERE {
  <http://www.fosi.org/projects/powder/multiple_examples.rdf#DR1> ?p ?o
}

Which gives us a lot of information

Count p o
1 http://www.w3.org/2007/05/powder#hasScopeblank node r1180000947r18520r1
2 http://purl.org/dc/terms/issued2007-05-17
3 http://xmlns.com/foaf/0.1/hasMakerhttp://www.example.com/foaf.rdf#me
4 http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#WDR
5 http://www.w3.org/2007/05/powder#validUntil2008-05-17
6 http://www.w3.org/2007/05/powder#hasDescriptionblank node r1180000947r18520r2

Incidentally, I've given the full URI of the particular DR as the subject. SPARQL defines a way to get data FROM a named graph in the data so that we could re-write Query 2 as:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?p ?o
FROM <http://www.fosi.org/projects/powder/multiple_examples.rdf#DR1>
WHERE {
  ?x ?p ?o
}

Which looks and feels better - but this is a new feature of SPARQL yet to be implemented in Redland which is what I've been using here (so I can't test it with the tools I have available).

This is a very general query that tells us all the predicates and objects of the DR, so everything we want to know is here.

But - two of our key bits of information are in blank nodes. We can solve this in two ways:

  1. Run a more specific query looking for precise information (which risks missing something that might be important)
  2. Run a second, more specific query now we can be sure we know what to look for.

Let's try those out.

This asks for specific information that we're looking for

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?maker ?setProp ?setValue ?dsProp ?dsValue ?issued ?validUntil
WHERE {
  <#DR1> foaf:hasMaker ?maker .
  <#DR1> wdr:hasScope ?rs .
  ?rs ?setProp ?setValue .
  <#DR1> wdr:hasDescription ?ds .
  ?ds ?dsProp ?dsValue .

  OPTIONAL {<#DR1> dcterms:issued ?issued}
  OPTIONAL {<#DR1> wdr:validUntil ?validUntil}

}

This does return everything we want to know about the DR - attribution, scope and description, plus issue and valid until dates.

Count maker setProp setValue dsProp dsValue issued validUntil
1 http://www.example.com/foaf.rdf#mehttp://www.w3.org/2007/05/powder#hasAnyHostFromexample.orghttp://example.org#colourblack2007-05-172008-05-17
2 http://www.example.com/foaf.rdf#mehttp://www.w3.org/2007/05/powder#hasAnyHostFromexample.orghttp://example.org#shapesquare2007-05-172008-05-17
3 http://www.example.com/foaf.rdf#mehttp://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#ResourceSethttp://example.org#colourblack2007-05-172008-05-17
4 http://www.example.com/foaf.rdf#mehttp://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#ResourceSethttp://example.org#shapesquare2007-05-172008-05-17

The drawback of this approach is that it would ignore any additional information that might be included. Also, someone might define their own vocabulary that they then used owl:sameAs or similar to say that those 'new' terms were related to our foaf:hasMaker etc. That should, I think, still be valid but we'd miss it. This is a weak argument! The idea of getting everything out of a DR in one query is very appealing.

The alternative is to issue specific queries once we can be sure what we're dealing with.

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT DISTINCT ?setProp ?setValue
WHERE {
  <#DR1> wdr:hasScope ?rs .
  ?rs ?setProp ?setValue
}

This tells us all about the Resource Set definition for DR 1 and gives us

Count setProp setValue
1 http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#ResourceSet
2 http://www.w3.org/2007/05/powder#hasAnyHostFromexample.org

We can run a similar query to get the details of the description

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT DISTINCT ?dsProp ?dsValue
WHERE {
  <#DR1> wdr:hasDescription ?ds .
  ?ds ?dsProp ?dsValue
}

Which gives us

Count dsProp dsValue
1 http://example.org#colourblack
2 http://example.org#shapesquare

So far then, Query 1 tells us that our source file has 6 DRs in it. From a processing point of view, we'd want to know this to be sure we were indeed looking at some POWDER data.

We can then either use Query 3 to take a strict approach to getting everything we need in one go from a particular DR, or we can be a bit more forgiving/flexible and use queries 2, 4 and 5 to get this data. So far then. I 'd say, Query 3 is looking good!

Let's try Query 3 - the strict but get it all in one query - on DR 2.

This is a repeat of query 3 made on <#DR2> rather than <#DR1>

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?maker ?setProp ?setValue ?dsProp ?dsValue ?issued ?validUntil
WHERE {
  <#DR2> foaf:hasMaker ?maker .
  <#DR2> wdr:hasScope ?rs .
  ?rs ?setProp ?setValue .
  <#DR2> wdr:hasDescription ?ds .
  ?ds ?dsProp ?dsValue .

  OPTIONAL {<#DR2> dcterms:issued ?issued}
  OPTIONAL {<#DR2> wdr:validUntil ?validUntil}

}

This gives us

Count maker setProp setValue dsProp dsValue issued validUntil
1 http://www.example.com/foaf.rdf#mehttp://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#ResourceSethttp://example.org#shapesquare2007-05-172008-05-17
2 http://www.example.com/foaf.rdf#mehttp://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#ResourceSethttp://example.org#colourblack2007-05-172008-05-17
3 http://www.example.com/foaf.rdf#mehttp://www.w3.org/2007/05/powder#hasAnyHostFromexample.org example.comhttp://example.org#shapesquare2007-05-172008-05-17
4 http://www.example.com/foaf.rdf#mehttp://www.w3.org/2007/05/powder#hasAnyHostFromexample.org example.comhttp://example.org#colourblack2007-05-172008-05-17
5 http://www.example.com/foaf.rdf#mehttp://www.w3.org/2007/05/powder#pathStartsWithAnyOffoo barhttp://example.org#shapesquare2007-05-172008-05-17
6 http://www.example.com/foaf.rdf#mehttp://www.w3.org/2007/05/powder#pathStartsWithAnyOffoo barhttp://example.org#colourblack2007-05-172008-05-17

We get multiple instances of the data but we can see that everything on example.com or example.org is square and black according to http://www.example.com/foaf.rdf#me on 2007-05-17, an assertion they'll stand by until 2008-05-17.

Notice in DR2 that the description has been removed from the DR (as we've seen in many of our examples to date).

This is looking too easy. In DR 3 the RS definition is separated out and put in a separate block in the same file, whilst the description is moved to a completely different RDF instance. How does Query 3 cope?

Another repeat of query 3, this time against <#DR3>

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?maker ?setProp ?setValue ?dsProp ?dsValue ?issued ?validUntil
WHERE {
  <#DR3> foaf:hasMaker ?maker .
  <#DR3> wdr:hasScope ?rs .
  ?rs ?setProp ?setValue .
  <#DR3> wdr:hasDescription ?ds .
  ?ds ?dsProp ?dsValue .

  OPTIONAL {<#DR3> dcterms:issued ?issued}
  OPTIONAL {<#DR3> wdr:validUntil ?validUntil}

}

Which gives a result of

Count maker setProp setValue dsProp dsValue issued validUntil

Oops.

Because the description is in a different RDF instance, the SPARQL query can't be completed.

I tried wrapping both the Resource Set and Description in OPTIONAL modifiers as in query 8

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?maker ?rs ?setProp ?setValue ?ds ?dsProp ?dsValue ?issued ?validUntil
WHERE {
  <#DR3> foaf:hasMaker ?maker .
  <#DR3> wdr:hasScope ?rs.
  <#DR3> wdr:hasDescription ?ds .

  OPTIONAL {?rs ?setProp ?setValue} .
  OPTIONAL {?ds ?dsProp ?dsValue} .
  OPTIONAL {<#DR3> dcterms:issued ?issued} .
  OPTIONAL {<#DR3> wdr:validUntil ?validUntil}
}

but that didn't work either. This could be a limitation of the Redland RDF kit - I have a feeling it is - but it's probably not going to be the only one that has difficulty with having to fetch bits of RDF from other sources.

Therefore, it seems that the safe way to do this is to work through the DR step by step. Let's go back to query 2 and find out everything we can about this DR.

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?p ?o
WHERE {
  <#DR3> ?p ?o
}

This gives us the following result:

Count p o
1 http://purl.org/dc/terms/issued2007-05-17
2 http://www.w3.org/2007/05/powder#hasDescriptionhttp://www.example.com/polygon
3 http://www.w3.org/2007/05/powder#validUntil2008-05-17
4 http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#WDR
5 http://xmlns.com/foaf/0.1/hasMakerhttp://www.example.com/foaf.rdf#me
6 http://www.w3.org/2007/05/powder#hasScopehttp://www.fosi.org/projects/powder/multiple_examples.rdf#RS3

We can see that we have our 3 key properties of foaf:hasMaker, wdr:hasScope and wdr:hasDescription and we have the URIs of those objects. We also have the issue and valid until dates.

Now we can run specific queries using the data we have as input.

First the scope, which, from line 6 the table above we see is at #RS3.

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?p ?o
WHERE {
  <#RS3> ?p ?o
}

Gives

Count p o
1 http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#ResourceSet
2 http://www.w3.org/2007/05/powder#hasAnyHostFromexample.org example.com
3 http://www.w3.org/2007/05/powder#pathStartsWithAnyOffoo bar

Which is nice and clear I think.

We can repeat this for the description but will notice that we will be looking at a different RDF instance, this time http://www.example.com/polygon (which doesn't exist so there's no point running the query!)

Likewise, if we want to, we could run a query on the object of the foaf:hasMaker property.

To recap, as things like RS definitions and Descriptions can easily be in locations other than the RDF instance that contains the basic DR, we must run separate queries for those elements.

In the example dataset, DR4 introduces anotherr twist - the use of OWL set operators. How do our queries get on now?

First let's find out what we can with the a simple query (Query 2 modified to refer to DR4)

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?p ?o
WHERE {
  <#DR4> ?p ?o
}

This gives is the result

Count p o
1 http://xmlns.com/foaf/0.1/hasMakerhttp://www.example.com/foaf.rdf#me
2 http://www.w3.org/2007/05/powder#hasScopeblank node r1180011514r30699r4
3 http://www.w3.org/2007/05/powder#validUntil2008-05-17
4 http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#WDR
5 http://www.w3.org/2007/05/powder#hasDescriptionhttp://www.example.org/foo
6 http://purl.org/dc/terms/issued2007-05-17

Which shows a blank node for wdr:hasScope. So we need to run a slightly different query now.

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?rs ?p ?o
WHERE {
  <#DR4> wdr:hasScope ?rs .
  ?rs ?p ?o
}

Which gives us

Count rs p o
1 blank node r1180012535r30816r4http://www.w3.org/2002/07/owl#unionOfblank node r1180012535r30816r6
2 blank node r1180012535r30816r4http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#ResourceSet

So now we know that our Resource Set uses owl:unionOf.

Now we know enough to start looking at the Collection of Resource Sets that are combined using owl:unionOf

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?rs ?rs1 ?p ?o
WHERE {
  <#DR4> wdr:hasScope ?rs .
  ?rs owl:unionOf ?a .
  ?a rdf:first ?rs1 .
  ?rs1 ?p ?o
}

Which gives

Count rs rs1 p o
1 blank node r1180013645r22330r4blank node r1180013645r22330r5http://www.w3.org/2007/05/powder#hasAnyHostFromexample.org
2 blank node r1180013645r22330r4blank node r1180013645r22330r5http://www.w3.org/2007/05/powder#pathStartsWithAnyOffoo bar
3 blank node r1180013645r22330r4blank node r1180013645r22330r5http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#ResourceSet

This gives us the data for the first RS in the union. Now we need the next RS which requires another query, but notice that it is similar.

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?rs ?rs2 ?p ?o
WHERE {
  <#DR4> wdr:hasScope ?rs .
  ?rs owl:unionOf ?a .
  ?a rdf:rest ?b .
  ?b rdf:first ?rs2
  ?rs2 ?p ?o
}

Which gives

Count rs rs2 p o
1 blank node r1180013895r28351r4blank node r1180013895r28351r7http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#ResourceSet
2 blank node r1180013895r28351r4blank node r1180013895r28351r7http://www.w3.org/2007/05/powder#pathStartsWithAnyOfbar
3 blank node r1180013895r28351r4blank node r1180013895r28351r7http://www.w3.org/2007/05/powder#hasAnyHostFromexample.net

We now know the details of the second RS in the union but we don't know whether there is a third so we modify the query again

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?rs ?rs3 ?p ?o
WHERE {
  <#DR4> wdr:hasScope ?rs .
  ?rs owl:unionOf ?a .
  ?a rdf:rest ?b .
  ?b rdf:rest ?c
  ?c rdf:first ?rs3
  ?rs3 ?p ?o
}

Which gives:

Count rs rs3 p o

As this is empty, we know we've reached the end and therefore we have all the data we need to create determine whether or not the candidate resource is or is not in the RS.

So how does all this work with sets derfined by property resource?

DR 5 contains such a Resource Set. Again we'll start with a modified version of Query 2 to get the basic dfata about DR 5

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?rs ?p ?o
WHERE {
  <#DR5> ?p ?o
}

And we get the result back

Count rs p o
1  http://www.w3.org/2007/05/powder#validUntil2008-05-17
2  http://www.w3.org/2007/05/powder#hasScopeblank node r1180036858r5649r9
3  http://www.w3.org/2007/05/powder#hasDescriptionhttp://www.example.org/foo
4  http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#WDR
5  http://xmlns.com/foaf/0.1/hasMakerhttp://www.example.com/foaf.rdf#me
6  http://purl.org/dc/terms/issued2007-05-17

As with DR4, we have DR wdr:hasScope blank node so we need to run Query 12 and see what we get

A modified version of Query 12 to look at the blank node given as scope

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?rs ?p ?o
WHERE {
  <#DR5> wdr:hasScope ?rs .
  ?rs ?p ?o
}

Which gives us

Count rs p o
1 blank node r1180014404r19324r9http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#ResourceSet
2 blank node r1180014404r19324r9http://www.w3.org/2007/05/powder#resourcesWithblank node r1180014404r19324r10
3 blank node r1180014404r19324r9http://www.w3.org/2007/05/powder#hasPropLookUpblank node r1180014404r19324r11

This is quite a different result to the one we got with Query 12. We need to find out what property we're looking for and how to find it.

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?rs ?p ?o ?mustHave ?lookUpProp ?lookUpValue
WHERE {
  <#DR5> wdr:hasScope ?rs .
  ?rs wdr:resourcesWith ?mustHave .
  ?mustHave ?p ?o.
  OPTIONAL {?rs wdr:hasPropLookUp ?look}
  OPTIONAL {?look ?lookUpProp ?lookUpValue}
}

Which gives

Count rs p o mustHave lookUpProp lookUpValue
1 blank node r1180039697r17448r9http://example.org#langfrblank node r1180039697r17448r10http://www.w3.org/2007/05/powder#methodhttp://www.w3.org/2006/http#HeadRequest
2 blank node r1180039697r17448r9http://example.org#langfrblank node r1180039697r17448r10http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#PropLookUp
3 blank node r1180039697r17448r9http://example.org#langfrblank node r1180039697r17448r10http://www.w3.org/2007/05/powder#responseContainsContent-Language: fr
4 blank node r1180039697r17448r9http://example.org#langfrblank node r1180039697r17448r10http://www.w3.org/2007/05/powder#lookUpURI$cURI

In reality, if query 17 revealed that there was a look up method available, you wouldn't need to look at the actual property since there's enough in the look up to tell you all you need to know. But the important point is that queries 17 and 18 extract all the necessary data.

As seems traditional, let's end up with a nasty one - it's not the nastiest imaginable - but it's pretty nasty.

DR 6 has a union of two Resource Sets AND a property definition.

Start with Query 2, modified to look at DR 6

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?p ?o
WHERE {
  <#DR6> ?p ?o
}

Which gives

Count p o
1 http://www.w3.org/2007/05/powder#hasDescriptionhttp://www.example.org/foo
2 http://purl.org/dc/terms/issued2007-05-17
3 http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#WDR
4 http://www.w3.org/2007/05/powder#hasScopeblank node r1180015158r30782r12
5 http://xmlns.com/foaf/0.1/hasMakerhttp://www.example.com/foaf.rdf#me
6 http://www.w3.org/2007/05/powder#validUntil2008-05-17

Which starting to look nice and familiar now. We see that wdr:hasScope has a blank node so we run a modified Query 12

BASE <http://www.fosi.org/projects/powder/multiple_examples.rdf>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX owl: <http://www.w3.org/2002/07/owl#>
PREFIX dcterms: <http://purl.org/dc/terms/>
PREFIX wdr: <http://www.w3.org/2007/05/powder#>
PREFIX ex: <http://example.org#>

SELECT ?rs ?p ?o
WHERE {
  <#DR6> wdr:hasScope ?rs .
  ?rs ?p ?o
}

Which gives

Count rs p o
1 blank node r1180015271r20630r12http://www.w3.org/2007/05/powder#hasPropLookUpblank node r1180015271r20630r18
2 blank node r1180015271r20630r12http://www.w3.org/2007/05/powder#resourcesWithblank node r1180015271r20630r17
3 blank node r1180015271r20630r12http://www.w3.org/2002/07/owl#unionOfblank node r1180015271r20630r14
4 blank node r1180015271r20630r12http://www.w3.org/1999/02/22-rdf-syntax-ns#typehttp://www.w3.org/2007/05/powder#ResourceSet

The results here show that we have an owl:unionOf and a wdr:resourcesWith predicate. We can follow both of those using modified versions of queries 13 - 15 and 18.

Summary

Query 1 is a good starting point as it tells us whether there are any DRs in the RDF data.

Query 2 gives us the basic predicates and objects of a given DR.

Which query is run next depends on the outcome of Query 2

If the object of wdr:hasScope is identified by a URI, run a query like Query 10 to find its predicates and objects. Likewise for wdr:hasDescription and, if desired, foaf:hasMaker.

If the object of wdr:hasScope is a blank node, run Query 12.

If the result of Query 12 shows that the Resource Set contains OWL Set Operators, run a series of queries like those in Query 13 - 15 to find the individual Resource Set Definitions that need to be combined.

If the result of Query 12 shows that the set is defined in terms of resource properties then run Query 18.

To Do

Consider DRS without Ids, work more examples and find the pitfalls.

Consider whether there is merit in encoding Resource Sets in XML - i.e. using a different query language for this aspect.