使用Jena遍历RDF

5

我现在正在为我的学习项目工作,需要一些帮助。

基本上,我需要将以下RDF转换为Java类的表示形式。我将RDF读入模型,但从那里开始便卡住了。

    StringReader in = new StringReader(resultTemp);
    Model model = ModelFactory.createDefaultModel();
    model.read(in, null, "TURTLE");

我尝试使用函数listSubjectsWithProperty(Property arg0, RDFNode arg1)和StmtIterator进行工作,但我无法理解它。

希望能得到一些帮助。

RDF:

@prefix d: <http://www.w3.org/2001/XMLSchema#> .
@prefix p: <http://parking.kmi.open.ac.uk/ontologies/parking#> .
@prefix s: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix g: <http://www.w3.org/2003/01/geo/wgs84_pos#> .
@prefix o: <http://linkedgeodata.org/ontology/> .

<http://parking.kmi.open.ac.uk/data/parks/4751.3> a o:Parking ;
    g:lat "50.8509406"^^d:double ;
    g:long "-0.983707"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/4934.6> a o:Parking ;
    g:lat "50.8737457"^^d:double ;
    g:long "-0.9731118"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/4934.8> a o:Parking ;
    g:lat "50.873617"^^d:double ;
    g:long "-0.9722267"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/4934.3> a o:Parking ;
    g:lat "50.8696495"^^d:double ;
    g:long "-0.9767757"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/4934.2> a o:Parking ;
    g:lat "50.8698594"^^d:double ;
    g:long "-0.9775482"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/4934.1> a o:Parking ;
    g:lat "50.8704349"^^d:double ;
    g:long "-0.9774731"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/4934.7> a o:Parking ;
    g:lat "50.8732887"^^d:double ;
    g:long "-0.9725968"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/28356.7> a o:Parking ;
    g:lat "50.997992"^^d:double ;
    g:long "-0.926222"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/40865.5> a o:Parking ;
    g:lat "50.995467"^^d:double ;
    g:long "-1.036603"^^d:double ;
    s:label "Workhouse Lane" ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/7185.1> a o:Parking ;
    g:lat "50.9885711"^^d:double ;
    g:long "-1.0811721"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/33791.10> a o:Parking ;
    g:lat "50.887628"^^d:double ;
    g:long "-0.929626"^^d:double ;
    s:label "Locked at 17:30" ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/20810.1> a o:Parking ;
    g:lat "50.891515"^^d:double ;
    g:long "-0.964029"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/33791.11> a o:Parking ;
    g:lat "50.894162"^^d:double ;
    g:long "-0.927854"^^d:double ;
    s:label "Locked at 17:30" ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/41308.7> a o:Parking ;
    g:lat "50.848336"^^d:double ;
    g:long "-0.937472"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/41308.6> a o:Parking ;
    g:lat "50.849124"^^d:double ;
    g:long "-0.937969"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/38470.10> a o:Parking ;
    g:lat "50.849454"^^d:double ;
    g:long "-0.939969"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/33030.4> a o:Parking ;
    g:lat "50.850708"^^d:double ;
    g:long "-0.913150"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/33030.3> a o:Parking ;
    g:lat "50.850421"^^d:double ;
    g:long "-0.914416"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/41378.7> a o:Parking ;
    g:lat "50.851734"^^d:double ;
    g:long "-0.949425"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/23937.9> a o:Parking ;
    g:lat "50.854045"^^d:double ;
    g:long "-0.979164"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/23834.6> a o:Parking ;
    g:lat "50.849214"^^d:double ;
    g:long "-0.987087"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/23937.8> a o:Parking ;
    g:lat "50.847012"^^d:double ;
    g:long "-0.986388"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/23937.7> a o:Parking ;
    g:lat "50.845044"^^d:double ;
    g:long "-0.989708"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/23937.12> a o:Parking ;
    g:lat "50.844084"^^d:double ;
    g:long "-1.008944"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/30510.6> a o:Parking ;
    g:lat "50.821892"^^d:double ;
    g:long "-0.983163"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/30554.10> a o:Parking ;
    g:lat "50.822039"^^d:double ;
    g:long "-0.982497"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/25125.2> a o:Parking ;
    g:lat "50.825640"^^d:double ;
    g:long "-1.078993"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/25125.1> a o:Parking ;
    g:lat "50.824621"^^d:double ;
    g:long "-1.082243"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/25125> a o:Parking ;
    g:lat "50.824789"^^d:double ;
    g:long "-1.083873"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/7345.6> a o:Parking ;
    g:lat "50.8249235"^^d:double ;
    g:long "-1.0734443"^^d:double ;
    s:label "Cycle-World" ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/21282> a o:Parking ;
    g:lat "50.836295"^^d:double ;
    g:long "-1.071699"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/25113.1> a o:Parking ;
    g:lat "50.829433"^^d:double ;
    g:long "-1.065990"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/25125.5> a o:Parking ;
    g:lat "50.834706"^^d:double ;
    g:long "-1.074678"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/29282.1> a o:Parking ;
    g:lat "50.836060"^^d:double ;
    g:long "-1.075153"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

<http://parking.kmi.open.ac.uk/data/parks/41323.3> a o:Parking ;
    g:lat "50.853264"^^d:double ;
    g:long "-0.990290"^^d:double ;
    p:binaryAvailability "true"^^d:boole...`

你好,我需要遍历这些块中的每一个:

<http://parking.kmi.open.ac.uk/data/parks/4751.3> a o:Parking ;
    g:lat "50.8509406"^^d:double ;
    g:long "-0.983707"^^d:double ;
    p:binaryAvailability "true"^^d:boolean .

有没有迭代器或其他方法可以实现这个功能?

它们中有些有s:label,有些没有,这会有影响吗? - Joshua Taylor
每个“块”都是由四个或五个语句组成的一组。 - Joshua Taylor
2个回答

7
如果你想手动迭代所关注的数据并手动选择你想要的内容,那么你可以使用Jena Model API来实现。但是,我认为用SPARQL查询选择数据然后迭代生成的ResultSet会更容易。本答案的其余部分展示了如何实现这两种方法。
使用Jena Model API
如果您想手动执行此操作,则可以执行以下操作(注释解释了正在进行的操作):
import java.io.IOException;
import java.io.InputStream;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.ResIterator;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;


public class ParkingExample {
    public static void main(String[] args) throws IOException {
        // Read the model from whereever it comes from.  For this example, 
        // I made a local copy in parking.ttl and so I'm loading it as a 
        // resource.  You're already able to load the model, so this 
        // isn't so important.
        Model model = ModelFactory.createDefaultModel();
        try ( final InputStream in = ParkingExample.class.getResourceAsStream( "/parking.ttl" ) ) {
            model.read( in, null, "TTL" );
        }

        // Create some properties in advance for convenience.
        final Property g_lat = model.createProperty( "http://www.w3.org/2003/01/geo/wgs84_pos#lat" );
        final Property g_long = model.createProperty( "http://www.w3.org/2003/01/geo/wgs84_pos#long" );
        final Property p_binaryAvailability = model.createProperty( "http://parking.kmi.open.ac.uk/ontologies/parking#binaryAvailability" );

        // In N3, Turtle, and SPARQL, `a` is a shorthand for rdf:type.  That means
        // that each of the triples of the form 
        //
        //   <http://parking.kmi.open.ac.uk/data/parks/4934.1> a o:Parking
        //
        // is saying that the subject has rdf:type o:Parking.  That's how we'll retrieve
        // these resources.  We'll select subjects that have o_Parking as a value for 
        // rdf:type.  We'll predefine o_Parking for convenience.
        final Resource o_Parking = model.createResource( "http://linkedgeodata.org/ontology/Parking" );

        // Now we get an iterator over the resources that have type o_Parking.
        for ( final ResIterator res = model.listResourcesWithProperty( RDF.type, o_Parking ); res.hasNext(); ) {
            final Resource r = res.next();

            // For each one of them, it appears that they have a mandatory lat, lon, and binAvailability, 
            // so we can retrieve those values, assuming that they'll be there.
            final float lat = r.getRequiredProperty( g_lat ).getObject().asLiteral().getFloat();
            final float lon = r.getRequiredProperty( g_long ).getObject().asLiteral().getFloat();
            final boolean binAvailibility = r.getRequiredProperty( p_binaryAvailability ).getObject().asLiteral().getBoolean();

            // Some of the Parkings have an rdfs:label, but not all of them do.  For this, we'll retrieve
            // a statement, but since there might not be one, we have to check whether it's null.  If it 
            // is, then we'll make the label null, but otherwise we'll get the string value out of it.
            final Statement s = r.getProperty( RDFS.label );
            final String label = s == null ? null : s.getObject().asLiteral().getString();

            // Now you can do whatever you want with these values.  You could create an instance of another 
            // class, for instance.. I'll just print the values out.
            System.out.println( r + ":" +
                    "\n\tlatitude: " + lat +
                    "\n\tlongitude: " + lon +
                    "\n\tavailibility: " + binAvailibility +
                    "\n\tlabel: " + label );
        }
    }
}

这会产生这样的输出:
http://parking.kmi.open.ac.uk/data/parks/4751.3:
    latitude: 50.85094
    longitude: -0.983707
    availibility: true
    label: null
http://parking.kmi.open.ac.uk/data/parks/41378.7:
    latitude: 50.851734
    longitude: -0.949425
    availibility: true
    label: null
http://parking.kmi.open.ac.uk/data/parks/25125:
    latitude: 50.824787
    longitude: -1.083873
    availibility: true
    label: null
…

使用SPARQL查询

我认为使用SPARQL查询要简单得多。SPARQL查询可以让您编写确切类型的数据,包括可选值,并且您可以使用ResultSet API获取想要返回的特定值。在这种情况下,您需要像这样的查询:

prefix d: <http://www.w3.org/2001/XMLSchema#>
prefix p: <http://parking.kmi.open.ac.uk/ontologies/parking#>
prefix s: <http://www.w3.org/2000/01/rdf-schema#>
prefix g: <http://www.w3.org/2003/01/geo/wgs84_pos#>
prefix o: <http://linkedgeodata.org/ontology/>

select ?parking ?lat ?lon ?availability ?label where {
  ?parking a o:Parking ;
             g:lat ?lat ;
             g:long ?lon ;
             p:binaryAvailability ?availability .
  optional { ?parking s:label ?label }
}

以下是您如何在代码中使用它的方法:
import java.io.IOException;
import java.io.InputStream;

import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;


public class ParkingExample {
    public static void main(String[] args) throws IOException {

        final String query = 
         "prefix d: <http://www.w3.org/2001/XMLSchema#>\n" +
         "prefix p: <http://parking.kmi.open.ac.uk/ontologies/parking#>\n" +
         "prefix s: <http://www.w3.org/2000/01/rdf-schema#>\n" +
         "prefix g: <http://www.w3.org/2003/01/geo/wgs84_pos#>\n" +
         "prefix o: <http://linkedgeodata.org/ontology/>\n" +
         "\n" +
         "select ?parking ?lat ?lon ?availability ?label where {\n" +
         "  ?parking a o:Parking ;\n" +
         "             g:lat ?lat ;\n" +
         "             g:long ?lon ;\n" +
         "             p:binaryAvailability ?availability .\n" +
         "  optional { ?parking s:label ?label }\n" +
         "}";

        Model model = ModelFactory.createDefaultModel();
        try ( final InputStream in = ParkingExample.class.getResourceAsStream( "/parking.ttl" ) ) {
            model.read( in, null, "TTL" );
        }

        final QueryExecution exec = QueryExecutionFactory.create( query, model );
        final ResultSet rs = exec.execSelect();
        while ( rs.hasNext() ) {
            final QuerySolution qs = rs.next();
            System.out.println( qs.get( "parking" ) +
                    "\n\t" + qs.get( "lat" ) +
                    "\n\t" + qs.get( "lon" ) +
                    "\n\t" + qs.get( "availability" ) +
                    "\n\t" + qs.get( "label" ));
        }
    }
}

输出结果如下:
http://parking.kmi.open.ac.uk/data/parks/38470.10
    50.849454^^http://www.w3.org/2001/XMLSchema#double
    -0.939969^^http://www.w3.org/2001/XMLSchema#double
    true^^http://www.w3.org/2001/XMLSchema#boolean
    null
http://parking.kmi.open.ac.uk/data/parks/28356.7
    50.997992^^http://www.w3.org/2001/XMLSchema#double
    -0.926222^^http://www.w3.org/2001/XMLSchema#double
    true^^http://www.w3.org/2001/XMLSchema#boolean
    null
http://parking.kmi.open.ac.uk/data/parks/33791.11
    50.894162^^http://www.w3.org/2001/XMLSchema#double
    -0.927854^^http://www.w3.org/2001/XMLSchema#double
    true^^http://www.w3.org/2001/XMLSchema#boolean
    Locked at 17:30
…

5
你的问题是什么?你可以这样获取所有的三元组:

什么是你的确切问题?你可以像这样获取所有的三元组:

StmtIterator it =  model.listStatements();
while (it.hasNext()) {
     Statement stmt = it.next();
     // do your stuff with the Statement (which is a triple)
}

这解决了您的问题吗?

您可以使用SimpleSelector选择特定的三元组。您需要提供主语、谓语和宾语三个参数。您可以留空其中一些,表示“任何”。

因此,如果您想要所有带有binaryAvailability属性的三元组(但是任何对象或主语),则可以执行以下操作:

Selector selector = new SimpleSelector(null, model.getProperty(binaryAvailabilityURI), (RDFNode) null);  // you need to cast the last null as otherwise the method is ambigious
StmtIterator it =  model.listStatements(selector);

尝试按照以下方式迭代以获取您的块。我没有测试过,但我认为它应该可以工作:

// select all resources that are of type Parking
ResIterator blockIt = model.listResourcesWithProperty(null, model.getProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), model.getResource(parkingUri);
while (blockIt.hasNext()) {
    Resource currentParking = blockIt.next();
    // select all statements that have the current Parking entity as subject
    StmtIterator it = model.listStatements(currentParking, null, (RDFNode) null);
    while (it.hasNext()) {
         // here you will get all triples for the current Parking block
    }
}

不完全正确。有没有办法为语句中的每个组 (lat、long、binaryAvailability) 获取一个引用? - David Kleinmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接