RDF和Jena RDF API入门(2)

转载自 http://www.cnblogs.com/yuyd902/archive/2008/10/08/1306648.html

陈述 

RDF模型中的每一个箭头表示为一个陈述(statement)。每一个陈述声明了关于某个资源的某个事实。一个陈述由三部分组成。

主体,也就是箭头的出发的资源。
谓词,也就是标识箭头的属性。
客体,也就是箭头所指向的那个资源或文本。

一个陈述有时也叫做一个三元组的原因就是它由三部分组成。

一个RDF模型(译者注: 指Jena中的接口Model)是由一组陈述所组成的。在Tutorial2中,每调用一次addProperty函数就会在模型中增加另一个陈述。(因为一个模型是由一组陈述组成的,所以增加一个重复的陈述并不会产生任何意义。)Jena模型接口定义了一个 listStatements()方法,此方法会返回一个StmtIterator类型的变量。StmtItor是Java中Iterator的一个子类型,这个StmtIterator变量重复迭代了该接口模型中的所有陈述。StmtIterator类型中有一个方法nextStatement (),该方法会从iterator返回下一个陈述,(就和next()返回的一样,但是已将其映射为Statement类型)。接口 Statement提供了访问陈述中主体,谓词和客体的方法。

现在我们会用使用那个接口来扩展Tutorial2,使起列出所有的创建的陈述并将它们打印出来。此例完整的代码可以在Tutorial3中找到。

//  java code
//  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(" .");
}

 

# jruby code
require 'java'

module Java
    include_package 'com.hp.hpl.jena.rdf.model'
    include_package 'com.hp.hpl.jena.vocabulary'
   
    PersonURI = "http://somewhere/JohnSmith"
    GivenName = "John"
    FamilyName = "Smith"
    FullName = GivenName + " " + FamilyName
   
    model = Java::ModelFactory.createDefaultModel
   
    john_smith = \
        model.createResource(PersonURI)\
            .addProperty(VCARD::FN, FullName)\
            .addProperty(VCARD::N, \
                model.createResource()\
                .addProperty(VCARD::Given, GivenName)\
                .addProperty(VCARD::Family, FamilyName))
   
    iter = model.listStatements
   
     while iter.hasNext
        stmt = iter.nextStatement
        subject = stmt.getSubject
        predicate = stmt.getPredicate
         object = stmt.getObject
       
         print subject.toString
         print " " + predicate.toString + " "
         if  object.kind_of? Java:: Resource
             print  object.toString
         else
             print "\"" + object.toString + "\""
         end
        puts " ."
     end
end


因为一个陈述的客体可以是一个资源也可以是一个文本。getObject()方法会返回一个类型为RDFNode的客体,RDFNode是Resource和Literal类共同的超类。为了确定本例中的客体确切的类型,代码中使用 instanceof(jruby中使用Object#kind_of?)来确定其类型和相应的处理。运行后,此程序回产生与此相似的输出:

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" . 

现在你明白了为什么模型构建会更加清晰。如果你仔细观察,就会发现上面每一行都由三个域组成,这三个域分别代表了每一个陈述的主体,谓词和客体。在此模型中有四个箭头,所以会有四个陈述。“anon:14df86:ecc3dee17b:-7fff”是由Jena产生的一个内部标识符,它不是一个URI,也不应该与URI混淆。它只是Jena处理时使用的一个内部标号。

W3C的RDF核心工作小组定义了一个类似的表示符号称为N-三元组(N-Triples)。这个名字表示会使用“三元组符号”。在下一节中我们会看到Jena有一个内置的N-三元组写机制(writer)。

写RDF 

Jena设有读写XML形式的RDF方法。这些方法可以被用来将一个RDF模型保存到文件并在日后重新将其读回。

Tutorial3创建了一个模型并将其以三元组的形式输出。Tutorial4对Tutorial3做了修改,使其将此模型以RDF XML的形式输出到标准输出流中。这个代码依然十分简单:model.write可以带一个OutputStream的参数。

//  java code
//  now write the model in XML form to a file
model.write(System.out);

 

# jruby code
require 'java'

module Java
    include_package 'com.hp.hpl.jena.rdf.model'
    include_package 'com.hp.hpl.jena.vocabulary'
   
    PersonURI = "http://somewhere/JohnSmith"
    GivenName = "John"
    FamilyName = "Smith"
    FullName = GivenName + " " + FamilyName
   
    model = Java::ModelFactory.createDefaultModel
   
    john_smith = \
        model.createResource(PersonURI)\
            .addProperty(VCARD::FN, FullName)\
            .addProperty(VCARD::N, \
                model.createResource()\
                .addProperty(VCARD::Given, GivenName)\
                .addProperty(VCARD::Family, FamilyName))
   
    model.write(java.lang. System.out)
end


应该有类似的输出:

< 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:N  rdf:nodeID ="A0" />
     < vcard:FN >John Smith </ vcard:FN >
   </ rdf:Description >
</ rdf:RDF >


W3C的RDF规格说明书规定了如何用 XML的形式来表示RDF。RDF XML的语法十分复杂。读者可以在RDF核心工作小组制定的RDF入门篇(primer)中找到更详细的指导。但是不管怎么样,让我们先迅速看一下应该如何解释上面的RDF XML输出。

RDF 常常嵌入在一个<rdf:RDF>元素中。如果有其他的方法知道此XML是RDF的话,该元素是可以不写的。然而我们常常会使用它。在这个RDF元素中定义了两个在本文档中使用的命名空间。接下来是一个<rdf:Description>元素,此元素描述了URI为“http://somewhere/JohnSmith”的资源。如果其中的rdf:about属性被省略的话,这个元素就表示一个空白结点。

<vcard:FN>元素描述了此资源的一个属性。属性的名字“FN”是属于vcard命名空间的。RDF会通过连接命名空间前缀的URI和名字局部名“FN”来形成该资源的URI“http://www.w3.org/2001/vcard-rdf/3.0#FN”。这个属性的值为文本“John Smith”。

<vcard:N>元素是一个资源。在此例中,这个资源是用一个相对URI来表示的。RDF会通过连接这个相对URI和此文档的基准URI来把它转换为一个绝对URI。

但是,在这个RDF XML输出中有一个错误,它并没有准确地表示我们所创建的模型。模型中的空白结点被分配了一个URI,它不再是空白的了。RDF/XML语法并不能表示所有的RDF模型。例如它不能表示一个同时是两个陈述的客体的空白结点。我们用来写这个RDF/XML的“哑”writer方法并没有试图去正确的书写这个模型的子集,虽然其原本可以被正确书写。它给每一个空白结点一个URI,使其不再空白。

Jena 有一个扩展的接口,它允许新的为不同的RDF串行化语言设计的writer可以被轻易地插入。以上的调用会激发一个标准的“哑”writer方法。Jena也包含了一个更加复杂的RDF/XML writer,它可以被用携带另一个参数的write()方法所调用。

//  java code
//  now write the model in XML form to a file
model.write(System.out, "RDF/XML-ABBREV"); 

 

#  jruby code
model.write(java.lang. System.out, 'RDF/XML-ABBREV')


此writer,也就是所谓的PrettyWriter,利用RDF/XML缩写语法把模型写地更为紧凑。它也能保存尽可能保留空白结点。然而,它并不合适来输出大的模型。因为它的性能不可能被人们所接受。要输出大的文件和保留空白结点,可以用N-三元组的形式输出:

//  java code
//  now write the model in XML form to a file
model.write(System.out, "N-TRIPLE");

 

#  jruby code
model.write(java.lang. System.out, 'N-TRIPLE')


这会产生类似于Tutorial3的输出, 此输出会遵循N-三元组的规格。

读RDF 

Tutorial 5 演示了如何将用RDF XML记录的陈述读入一个模型。在此例中,我们提供了一个小型RDF/XML形式的vcard的数据库。下面代码会将其读入和写出。注意:如果要运行这个小程序,应该把输入文件放在你的当前目录下。

文件“vc-db-1.rdf”可以在“$JenaInstallPath/doc/tutorial/RDF_API/data/”中找到。

//  java code
//  create an empty model
Model model = ModelFactory.createDefaultModel();

//  use the class loader to find the input file
InputStream in = Tutorial05. class
                              .getClassLoader()
                              .getResourceAsStream(inputFileName);
if (in ==  null) {
     throw  new IllegalArgumentException(
                                 "File: " + inputFileName + " not found");
}

// read the RDF/XML file 
model.read(new InputStreamReader(in), ""); 

// write it to standard out 
model.write(System.out); 

 

#  jruby code
require 'java'

module Java
    include_package 'com.hp.hpl.jena.rdf.model'
    include_package 'com.hp.hpl.jena.vocabulary'
    include_package 'com.hp.hpl.jena.util'
    include_package 'java.io'
   
    InputFileName = 'vc-db-1.rdf'
   
    model = Java::ModelFactory.createDefaultModel
    input_stream = Java::FileManager.get.open InputFileName
     if input_stream == nil
        raise ArgumentError, "File:"  + InputFileName + "not found"
     end
    model.read input_stream, ''
    model.write java.lang. System.out
end


read()方法中的第二个参数是一个URI,它是被用来解决相对URI的。因为在测试文件中没有使用相对URI,所以它允许被置为空值。运行时,Tutorial5会产生类似如下的XML输出

< 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:Given >John </ vCard:Given >
     < vCard:Family >Smith </ vCard:Family >
   </ rdf:Description >
   < rdf:Description  rdf:about ="http://somewhere/RebeccaSmith/" >
     < vCard:N  rdf:nodeID ="A1" />
     < vCard:FN >Becky Smith </ vCard:FN >
   </ rdf:Description >
   < rdf:Description  rdf:nodeID ="A2" >
     < vCard:Given >Matthew </ vCard:Given >
     < vCard:Family >Jones </ vCard:Family >
   </ rdf:Description >
   < rdf:Description  rdf:nodeID ="A3" >
     < vCard:Given >Sarah </ vCard:Given >
     < vCard:Family >Jones </ vCard:Family >
   </ rdf:Description >
   < rdf:Description  rdf:about ="http://somewhere/MattJones/" >
     < vCard:N  rdf:nodeID ="A2" />
     < vCard:FN >Matt Jones </ vCard:FN >
   </ rdf:Description >
   < rdf:Description  rdf:nodeID ="A1" >
     < vCard:Given >Rebecca </ vCard:Given >
     < vCard:Family >Smith </ vCard:Family >
   </ rdf:Description >
   < rdf:Description  rdf:about ="http://somewhere/SarahJones/" >
     < vCard:N  rdf:nodeID ="A3" />
     < vCard:FN >Sarah Jones </ vCard:FN >
   </ rdf:Description >
   < rdf:Description  rdf:about ="http://somewhere/JohnSmith/" >
     < vCard:N  rdf:nodeID ="A0" />
     < vCard:FN >John Smith </ vCard:FN >
   </ rdf:Description >
</ rdf:RDF >

你可能感兴趣的:(api)