• RDF和Jena RDF API入门(2)

    普通类
    • 支持
    • 批判
    • 提问
    • 解释
    • 补充
    • 删除
    • 陈述


    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>

    • 标签:
    • java
    • rdf
    • xml
    • 模型
    • http
    • 陈述
    • api
    • vcard
    • 基础
    • jena
  • 加入的知识群:
    学习元评论 (0条)

    评论为空
    聪明如你,不妨在这 发表你的看法与心得 ~



    登录之后可以发表学习元评论
      
暂无内容~~
顶部