Este é um tutorial introdutório ao framework de descrição de recursos (RDF) e Jena, uma API Java para RDF. Ele é escrito para programadores que não estão familiarizados com RDF e que aprendem melhor através de prototipagem, ou, por outros motivos, desejam avançar rapidamente para a implementação. Familiaridade com XML e Java é assumido.
// some definitions static String personURI = "http://somewhere/JohnSmith"; static String fullName = "John Smith"; // create an empty Model Model model = ModelFactory.createDefaultModel(); // create the resource Resource johnSmith = model.createResource(personURI); // add the property johnSmith.addProperty(VCARD.FN, fullName);
Resource johnSmith = model.createResource(personURI) .addProperty(VCARD.FN, fullName);
// some definitions String personURI = "http://somewhere/JohnSmith"; String givenName = "John"; String familyName = "Smith"; String fullName = givenName + " " + familyName; // create an empty Model Model model = ModelFactory.createDefaultModel(); // create the resource // and add the properties cascading style Resource johnSmith = model.createResource(personURI) .addProperty(VCARD.FN, fullName) .addProperty(VCARD.N, model.createResource() .addProperty(VCARD.Given, givenName) .addProperty(VCARD.Family, familyName));
// list the statements in the Model StmtIterator iter = model.listStatements(); // print out the predicate, subject and object of each statement while (iter.hasNext()) { Statement stmt = iter.nextStatement(); // get next statement Resource subject = stmt.getSubject(); // get the subject Property predicate = stmt.getPredicate(); // get the predicate RDFNode object = stmt.getObject(); // get the object System.out.print(subject.toString()); System.out.print(" " + predicate.toString() + " "); if (object instanceof Resource) { System.out.print(object.toString()); } else { // object is a literal System.out.print(" \"" + object.toString() + "\""); } System.out.println(" ."); }
http://somewhere/JohnSmith http://www.w3.org/2001/vcard-rdf/3.0#N anon:14df86:ecc3dee17b:-7fff . anon:14df86:ecc3dee17b:-7fff http://www.w3.org/2001/vcard-rdf/3.0#Family "Smith" . anon:14df86:ecc3dee17b:-7fff http://www.w3.org/2001/vcard-rdf/3.0#Given "John" . http://somewhere/JohnSmith http://www.w3.org/2001/vcard-rdf/3.0#FN "John Smith" .
// now write the model in XML form to a file model.write(System.out);
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:vcard='http://www.w3.org/2001/vcard-rdf/3.0#' > <rdf:Description rdf:about='http://somewhere/JohnSmith'> <vcard:FN>John Smith</vcard:FN> <vcard:N rdf:nodeID="A0"/> </rdf:Description> <rdf:Description rdf:nodeID="A0"> <vcard:Given>John</vcard:Given> <vcard:Family>Smith</vcard:Family> </rdf:Description> </rdf:RDF>
// now write the model in a pretty form RDFDataMgr.write(System.out, model, Lang.RDFXML);
// now write the model in XML form to a file RDFDataMgr.write(System.out, model, Lang.NTRIPLES);
// create an empty model Model model = ModelFactory.createDefaultModel(); // use the RDFDataMgr to find the input file InputStream in = RDFDataMgr.open( inputFileName ); if (in == null) { throw new IllegalArgumentException( "File: " + inputFileName + " not found"); } // read the RDF/XML file model.read(in, null); // write it to standard out model.write(System.out);
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:vcard='http://www.w3.org/2001/vcard-rdf/3.0#' > <rdf:Description rdf:nodeID="A0"> <vcard:Family>Smith</vcard:Family> <vcard:Given>John</vcard:Given> </rdf:Description> <rdf:Description rdf:about='http://somewhere/JohnSmith/'> <vcard:FN>John Smith</vcard:FN> <vcard:N rdf:nodeID="A0"/> </rdf:Description> <rdf:Description rdf:about='http://somewhere/SarahJones/'> <vcard:FN>Sarah Jones</vcard:FN> <vcard:N rdf:nodeID="A1"/> </rdf:Description> <rdf:Description rdf:about='http://somewhere/MattJones/'> <vcard:FN>Matt Jones</vcard:FN> <vcard:N rdf:nodeID="A2"/> </rdf:Description> <rdf:Description rdf:nodeID="A3"> <vcard:Family>Smith</vcard:Family> <vcard:Given>Rebecca</vcard:Given> </rdf:Description> <rdf:Description rdf:nodeID="A1"> <vcard:Family>Jones</vcard:Family> <vcard:Given>Sarah</vcard:Given> </rdf:Description> <rdf:Description rdf:nodeID="A2"> <vcard:Family>Jones</vcard:Family> <vcard:Given>Matthew</vcard:Given> </rdf:Description> <rdf:Description rdf:about='http://somewhere/RebeccaSmith/'> <vcard:FN>Becky Smith</vcard:FN> <vcard:N rdf:nodeID="A3"/> </rdf:Description> </rdf:RDF>
Na sessão anterior, nós vimos que a saída XML declarou um prefixo namespace
vcard e o usou para abreviar URIs. Enquanto que RDF usa somente URIs completas, e não sua forma encurtada, Jena provê formas de controlar namespaces usados na saída com seu mapeamento de prefixos. Aqui vai um exemplo simples.
Model m = ModelFactory.createDefaultModel(); String nsA = "http://somewhere/else#"; String nsB = "http://nowhere/else#"; Resource root = m.createResource( nsA + "root" ); Property P = m.createProperty( nsA + "P" ); Property Q = m.createProperty( nsB + "Q" ); Resource x = m.createResource( nsA + "x" ); Resource y = m.createResource( nsA + "y" ); Resource z = m.createResource( nsA + "z" ); m.add( root, P, x ).add( root, P, y ).add( y, Q, z ); System.out.println( "# -- no special prefixes defined" ); m.write( System.out ); System.out.println( "# -- nsA defined" ); m.setNsPrefix( "nsA", nsA ); m.write( System.out ); System.out.println( "# -- nsA and cat defined" ); m.setNsPrefix( "cat", nsB ); m.write( System.out );
A saída deste fragmento são três blocos de RDF/XML, com três diferentes mapeamentos de prefixos. Primeiro o padrão, sem prefixos diferentes dos padrões:
# -- no special prefixes defined <rdf:RDF xmlns:j.0="http://nowhere/else#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:j.1="http://somewhere/else#" > <rdf:Description rdf:about="http://somewhere/else#root"> <j.1:P rdf:resource="http://somewhere/else#x"/> <j.1:P rdf:resource="http://somewhere/else#y"/> </rdf:Description> <rdf:Description rdf:about="http://somewhere/else#y"> <j.0:Q rdf:resource="http://somewhere/else#z"/> </rdf:Description> </rdf:RDF>
Nós vimos que o namespace rdf é declarado automaticamente, já que são requeridos para tags como <RDF:rdf> e <rdf:resource>. Declarações de namespace são também necessárias para o uso das duas propriedades P e Q, mas já que seus namespaces não foram introduzidos no modelo, eles recebem nomes namespaces inventados j.0 e j.1.
# -- nsA defined <rdf:RDF xmlns:j.0="http://nowhere/else#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:nsA="http://somewhere/else#" > <rdf:Description rdf:about="http://somewhere/else#root"> <nsA:P rdf:resource="http://somewhere/else#x"/> <nsA:P rdf:resource="http://somewhere/else#y"/> </rdf:Description> <rdf:Description rdf:about="http://somewhere/else#y"> <j.0:Q rdf:resource="http://somewhere/else#z"/> </rdf:Description> </rdf:RDF>
O outro namespace ainda recebe o nome criado automaticamente, mas o nome nsA é agora usado nas tags de propriedades. Não há necessidade de que o nome do prefixo tenha alguma relação com as variáveis do código Jena:
# -- nsA and cat defined <rdf:RDF xmlns:cat="http://nowhere/else#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:nsA="http://somewhere/else#" > <rdf:Description rdf:about="http://somewhere/else#root"> <nsA:P rdf:resource="http://somewhere/else#x"/> <nsA:P rdf:resource="http://somewhere/else#y"/> </rdf:Description> <rdf:Description rdf:about="http://somewhere/else#y"> <cat:Q rdf:resource="http://somewhere/else#z"/> </rdf:Description> </rdf:RDF>
Ambos os prefixos são usados na saída, e não houve a necessidade de prefixos gerados automaticamente.
Assim como as declarações de prefixos definidas por chamadas a setNsPrefix, Jena vai lembrar-se dos prefixos que foram usados na entrada para model.read().
Model m2 = ModelFactory.createDefaultModel(); m2.read( "file:/tmp/fragment.rdf" ); m2.write( System.out );
Você verá que os prefixos da entrada são preservados na saída. Todos os prefixos são escritos, mesmo se eles não forem usados em lugar algum. Você pode remover um prefixo com removeNsPrefix(String prefix) se você não o quiser na saída.
// retrieve the John Smith vcard resource from the model Resource vcard = model.getResource(johnSmithURI);
// retrieve the value of the N property Resource name = (Resource) vcard.getProperty(VCARD.N) .getObject();
// retrieve the value of the N property Resource name = vcard.getProperty(VCARD.N) .getResource();
String fullName = vcard.getProperty(VCARD.FN) .getString();
// add two nickname properties to vcard vcard.addProperty(VCARD.NICKNAME, "Smithy") .addProperty(VCARD.NICKNAME, "Adman");
// set up the output System.out.println("The nicknames of \"" + fullName + "\" are:"); // list the nicknames StmtIterator iter = vcard.listProperties(VCARD.NICKNAME); while (iter.hasNext()) { System.out.println(" " + iter.nextStatement() .getObject() .toString()); }
The nicknames of "John Smith" are: Smithy Adman
// list vcards ResIterator iter = model.listSubjectsWithProperty(VCARD.FN); while (iter.hasNext()) { Resource r = iter.nextResource(); ... }
Selector selector = new SimpleSelector(subject, predicate, object);
Selector selector = new SimpleSelector(null, null, null);
Selector selector = new SimpleSelector(null, VCARD.FN, null);
listStatements( S, P, O )
é equivalente a
listStatements( new SimpleSelector( S, P, O ) )
// select all the resources with a VCARD.FN property ResIterator iter = model.listSubjectsWithProperty(VCARD.FN); if (iter.hasNext()) { System.out.println("The database contains vcards for:"); while (iter.hasNext()) { System.out.println(" " + iter.nextResource() .getProperty(VCARD.FN) .getString()); } } else { System.out.println("No vcards were found in the database"); }
The database contains vcards for: Sarah Jones John Smith Matt Jones Becky Smith
// select all the resources with a VCARD.FN property // whose value ends with "Smith" StmtIterator iter = model.listStatements( new SimpleSelector(null, VCARD.FN, (RDFNode) null) { public boolean selects(Statement s) {return s.getString().endsWith("Smith");} });
The database contains vcards for: John Smith Becky Smith
// do all filtering in the selects method StmtIterator iter = model.listStatements( new SimpleSelector(null, null, (RDFNode) null) { public boolean selects(Statement s) { return (subject == null || s.getSubject().equals(subject)) && (predicate == null || s.getPredicate().equals(predicate)) && (object == null || s.getObject().equals(object)) ; } } });
StmtIterator iter = model.listStatements(new SimpleSelector(subject, predicate, object)
// read the RDF/XML files model1.read(new InputStreamReader(in1), ""); model2.read(new InputStreamReader(in2), ""); // merge the Models Model model = model1.union(model2); // print the Model as RDF/XML model.write(system.out, "RDF/XML-ABBREV");
<rdf:RDF xmlns:rdf="<a href="http://www.w3.org/1999/02/22-rdf-syntax-ns#">http://www.w3.org/1999/02/22-rdf-syntax-ns#</a>" xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#"> <rdf:Description rdf:about="http://somewhere/JohnSmith/"> <vcard:EMAIL> <vcard:internet> <rdf:value>John@somewhere.com</rdf:value> </vcard:internet> </vcard:EMAIL> <vcard:N rdf:parseType="Resource"> <vcard:Given>John</vcard:Given> <vcard:Family>Smith</vcard:Family> </vcard:N> <vcard:FN>John Smith</vcard:FN> </rdf:Description> </rdf:RDF>
// create a bag Bag smiths = model.createBag(); // select all the resources with a VCARD.FN property // whose value ends with "Smith" StmtIterator iter = model.listStatements( new SimpleSelector(null, VCARD.FN, (RDFNode) null) { public boolean selects(Statement s) { return s.getString().endsWith("Smith"); } }); // add the Smith's to the bag while (iter.hasNext()) { smiths.add(iter.nextStatement().getSubject()); }
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:vcard='http://www.w3.org/2001/vcard-rdf/3.0#' > ... <rdf:Description rdf:nodeID="A3"> <rdf:type rdf:resource='http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag'/> <rdf:_1 rdf:resource='http://somewhere/JohnSmith/'/> <rdf:_2 rdf:resource='http://somewhere/RebeccaSmith/'/> </rdf:Description> </rdf:RDF>
// print out the members of the bag NodeIterator iter2 = smiths.iterator(); if (iter2.hasNext()) { System.out.println("The bag contains:"); while (iter2.hasNext()) { System.out.println(" " + ((Resource) iter2.next()) .getProperty(VCARD.FN) .getString()); } } else { System.out.println("The bag is empty"); }
The bag contains: John Smith Becky Smith
// create the resource Resource r = model.createResource(); // add the property r.addProperty(RDFS.label, model.createLiteral("chat", "en")) .addProperty(RDFS.label, model.createLiteral("chat", "fr")) .addProperty(RDFS.label, model.createLiteral("<em>chat</em>", true)); // write out the Model model.write(system.out);
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:rdfs='http://www.w3.org/2000/01/rdf-schema#' > <rdf:Description rdf:nodeID="A0"> <rdfs:label xml:lang='en'>chat</rdfs:label> <rdfs:label xml:lang='fr'>chat</rdfs:label> <rdfs:label rdf:parseType='Literal'><em>chat</em></rdfs:label> </rdf:Description> </rdf:RDF>
// create the resource Resource r = model.createResource(); // add the property r.addProperty(RDFS.label, "11") .addProperty(RDFS.label, 11); // write out the Model model.write(system.out, "N-TRIPLE");
_:A... <http://www.w3.org/2000/01/rdf-schema#label> "11" .