• 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>
  • 相关阅读:
    期待着一个目标 和一个新生
    做一个真正意志坚强的人
    从猫叫、老鼠跑和人醒看观察者模式
    再看C++(6)操作符重载
    英尺
    再看C、C++、数据结构(三)
    一道比较有意思的打印题(不需要会很多计算机语言知识,简单的C就行)
    再看C++(四)const的终极使用
    再看C、C++、数据结构(二)
    再看C语言和数据结构(一)
  • 原文地址:https://www.cnblogs.com/chenying99/p/3125589.html
Copyright © 2020-2023  润新知