zoukankan      html  css  js  c++  java
  • 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>
  • 相关阅读:
    UVA 1025 A Spy in the Metro DP水题
    ZOJ 3814 Sawtooth Puzzle BFS
    ZOJ 3816 Generalized Palindromic Number
    UVA 10859 Placing Lampposts 树形DP
    UVA 11825 Hackers' Crackdown 状压DP
    POJ 2887 Big String 线段树 离线处理
    POJ 1635 Subway tree systems Hash法判断有根树是否同构
    BZOJ 3110 k大数查询 & 树套树
    sdoi 2009 & 状态压缩
    来自于2016.2.24的flag
  • 原文地址:https://www.cnblogs.com/chenying99/p/3125589.html
Copyright © 2011-2022 走看看