1

I have used Construct Sparql query to extract an RDF graph from dbpedia. Now the problem is that the extracted graph stores the properties (e.g birthplace) associated with the individuals (e.g Maria Sharapova) as annotations to the individual. How can I specify properties while constructing the graph? My code:

String service="http://dbpedia.org/sparql";String queryString =
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> "+
"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> "+
"PREFIX dbp: <http://dbpedia.org/property/> "+
"PREFIX dbpedia: <http://dbpedia.org/resource/> "+
    "PREFIX dbo: <http://dbpedia.org/ontology/> " +
    "CONSTRUCT { ?entity rdfs:label ?label . ?entity rdf:type dbo:TennisPlayer. ?entity dbp:birthPlace ?b.} " + 
    "where { "+
    "?entity rdfs:label ?label ."+
            "?entity rdf:type dbo:TennisPlayer."+
            "?entity dbp:birthPlace ?b." +             
"FILTER (lang(?label) = 'en')."+
    "}\n"
Query query = QueryFactory.create(queryString);
System.out.println("Query Result Sheet");
QueryExecution qe =QueryExecutionFactory.sparqlService(service, query);
Model results =  qe.execConstruct();
results.write(System.out, "RDF/XML");
String fileName = "D:/tayybah/GATE data/GATE ontologies/dbpedia domain.owl";
FileWriter outfile = new FileWriter( fileName );
results.write(outfile, "RDF/XML");
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
tayybah
  • 91
  • 1
  • 4
  • 3
    I don't think that your question is specific to Jena or your Java code, right? In that case, can you remove all the Java code and just present the pure SPARQL query, please? That would make things a lot easier to read and assess. – O. R. Mapper Oct 22 '14 at 13:00
  • 1
    Can you paste how the output is now and how you want it to look? I do not think SPARQL contruct has the functionality you are looking for. If I understand you correclty you want to add the properties to the "new" graph of entities, not just birthplace? – magnudae Oct 22 '14 at 13:00

2 Answers2

3

The way I've typically done this in the past (e.g., converting an RDFS vocabulary to SKOS in Is there a way to convert the data format of an RDF vocabulary to SKOS) is to use one or more values blocks to specify the each DBpedia type or property and its corresponding type or property in my own ontology. For instance, a construct query like:

construct {
  ?entity a ?mytype ; ?myprop ?value 
}
where {
  values (?dbtype ?mytype) {
    (dbpedia-owl:TennisPlayer my:PlayerOfTennis)
  }

  values (?dbprop ?myprop) {
    (rdfs:label my:label)
    (dbpprop:birthPlace my:placeOfBirth)
  }

  ?entity a ?dbtype ; ?dbprop ?value .
}

This grabs each entity of type ?dbtype and each of its values for ?dbprop, and constructs a graph with a corresponding entity of type ?mytype with the same value for the proeprty ?myprop. As Rob Hall pointed out, Protege will still think that my:label and my:placeOfBirth are annotation properties unless you include declarations for them. You can actually do that, too in the construct query. If you just add to what you have in your values block, this can be as easy as, e.g.,

construct {
  ?entity a ?type ; ?myprop ?value .
  ?myprop a ?proptype
}
where {
  values (?dbprop ?myprop ?proptype) {
    (dbpprop:birthPlace my:placeOfBirth owl:ObjectProperty)
    #-- ... 
  }
}

You can use the same approach to add in language filters, too. Just remember that you can use the keyword undef in values blocks, and that you can check in filters with unbound. Thus, as the final example, you can do:

prefix my: <http://example.org/vocab/>

construct {
  ?entity a ?mytype ; ?myprop ?value .
  ?mytype a owl:Class .
  ?myprop a ?proptype .
}
where {
  values (?dbtype ?mytype) {
    (dbpedia-owl:TennisPlayer my:PlayerOfTennis)
  }

  values (?dbprop ?myprop ?lang ?proptype) {
    (dbpedia-owl:birthPlace my:placeOfBirth undef owl:ObjectProperty)
    (rdfs:label my:label 'en' owl:AnnotationProperty)
  }

  ?entity a ?dbtype ; ?dbprop ?value .
   filter ( !bound(?lang) || langMatches(lang(?value),'en') )
}

SPARQL results

@prefix rdf:    <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix ns1:    <http://example.org/vocab/> .
@prefix dbpedia:    <http://dbpedia.org/resource/> .
@prefix owl:    <http://www.w3.org/2002/07/owl#> .

dbpedia:Maaike_Smit rdf:type    ns1:PlayerOfTennis ;
    ns1:label   "Maaike Smit"@en ;
    ns1:placeOfBirth    dbpedia:Netherlands ,
        dbpedia:Emmeloord .
dbpedia:Alexander_Kudryavtsev   rdf:type    ns1:PlayerOfTennis ;
    ns1:label   "Alexander Kudryavtsev"@en ;
    ns1:placeOfBirth    dbpedia:Yekaterinburg .
dbpedia:Alexander_Zverev    rdf:type    ns1:PlayerOfTennis ;
    ns1:label   "Alexander Zverev"@en ;
    ns1:placeOfBirth    dbpedia:Sochi .
dbpedia:Alina_Jidkova   rdf:type    ns1:PlayerOfTennis ;
    ns1:label   "Alina Jidkova"@en ;
    ns1:placeOfBirth    dbpedia:Soviet_Union ,
        dbpedia:Moscow .

# ...

ns1:PlayerOfTennis  rdf:type    owl:Class .
ns1:label   rdf:type    owl:AnnotationProperty .
ns1:placeOfBirth    rdf:type    owl:ObjectProperty .

With Jena in Java

import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;

import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;

public class DBpediaOntologyMappingExample {
    public static void main(String[] args) {
        String query = "\n"
                + "prefix owl: <http://www.w3.org/2002/07/owl#>\n"
                + "prefix dbpedia-owl: <http://dbpedia.org/ontology/>\n"
                + "prefix my: <http://example.org/vocab/>\n"
                + "prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>\n"
                + "\n"
                + "construct {\n"
                + "  ?entity a ?mytype ; ?myprop ?value .\n"
                + "  ?mytype a owl:Class .\n"
                + "  ?myprop a ?proptype .\n"
                + "}\n"
                + "where {\n"
                + "  values (?dbtype ?mytype) {\n"
                + "    (dbpedia-owl:TennisPlayer my:PlayerOfTennis)\n"
                + "  }\n"
                + "  values (?dbprop ?myprop ?lang ?proptype) {\n"
                + "    (dbpedia-owl:birthPlace my:placeOfBirth undef owl:ObjectProperty)\n"
                + "    (rdfs:label my:label 'en' owl:AnnotationProperty)\n"
                + "  }\n"
                + "  ?entity a ?dbtype ; ?dbprop ?value .\n"
                + "  filter ( !bound(?lang) || langMatches(lang(?value),'en') )\n"
                + "}\n"
                + "limit 100";

        String dbpedia = "http://dbpedia.org/sparql";
        QueryExecution exec = QueryExecutionFactory.sparqlService( dbpedia, query );
        RDFDataMgr.write( System.out, exec.execConstruct(), Lang.N3 );
    }
}
Community
  • 1
  • 1
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
  • One thing to note is that if you have the power to modify your `VALUES` block, then you can probably just include the schema portion verbatim in your `CONSTRUCT` clause. That is, you can just put `my:placeOfBirth a owl:ObjectProperty` in your `CONSTRUCT` clause. Readability aside, I'm not sure if it would introduce performance issues to do what I suggest. – Rob Hall Oct 22 '14 at 14:12
  • 1
    If someone has a large amount of schema structure that they want to import, then the most straight forward thing to do (in my opinion) would be to take the union of that schema and their construct query results outside the context of SPARQL (ie: in Jena). – Rob Hall Oct 22 '14 at 14:15
  • 1
    @RobHall Yeah, it could be included there, or you could have separate values blocks for object and datatype properties (with a union in the select query). There are lots of different options. If the mapping is known ahead of time, I think it'd even be a better idea to just define it in some OWL file and add an ontology header to the construct block that imports the mapping ontology. – Joshua Taylor Oct 22 '14 at 14:22
  • @Joshua Taylor thank u very much for your answer. It cleared many things. did you run this sparql query through jena or directly from sparql endpoint? Actually when i executed this query directly from [http://dbpedia.org/snorql] it works fine but when i execute it through jena it gives the following error `Exception in thread "main" HttpException: 500 at com.hp.hpl.jena.sparql.engine.http.HttpQuery.rewrap(HttpQuery.java:414) ...` – tayybah Oct 24 '14 at 04:38
  • @tayybah There are lots of ways that this could be run through Jena, so there's not enough information yet to diagnose that problem, but that problem really sounds different from the one you've got here, so it might be best asked as a new question. But, as a quick possibility, did you include all the prefix declarations that are necessary? The web-interface adds a bunch by default, but you need to specify them explicitly in your own Java code. – Joshua Taylor Oct 24 '14 at 12:35
  • @tayybah I added some Java code that uses Jena and runs the query. – Joshua Taylor Oct 24 '14 at 13:12
  • @ Joshua Taylor Thank u very much for your help . Yes my code also worked there was a wrongly used prefix inside the sparql query in my code. – tayybah Oct 27 '14 at 05:39
1

The graph shouldn't modify the properties in any way when created. When you view the graph in protege, however, it has no knowledge how to interpret the properties, and calls them annotations by default.

You have two options. Include a schema for DBPedia when interpreting the triples you extract (so protege can see triples describing the properties) or extract triples along with your construct query.

You don't seem to require definitions for anything beyond the dbp:bithPlace property, so the most trivial solution is to just add the missing triple manually:

final Model results =  qe.execConstruct();
results.add(results.getResource("http://dbpedia.org/property/birthPlace"),
            RDF.type, OWL.DatatypeProperty);

If you were to use many properties, or if you didn't know what properties you were going to retrieve, then you should either include the schemas directly (loading them into Jena models) or run a modified query that can pull properties about the properties.

EDIT

The following example shows just adding schema data directly to the results when necessary.

final Model schema = ModelFactory.createDefaultModel();
// TODO populate schema
// ...
final Model results = qe.execConstruct();
results.add(schema);
Rob Hall
  • 2,693
  • 16
  • 22