存档

文章标签 ‘JENA’

用jena api来理解RDFS——subClassOf subPropertyOf range domain

2010年1月9日

这四个词汇与推理密切相关,查看JENA的RDFSRuleReasonerFactory可以看到里面有这么一段代码:

  1. Resource base = capabilities.createResource(getURI());
  2. base.addProperty(ReasonerVocabulary.nameP, "RDFS FB-TGC Rule Reasoner")
  3. .addProperty(ReasonerVocabulary.descriptionP, "Complete RDFS implementation supporting metalevel statements.\nCan separate tbox and abox data if desired to reuse tbox caching or mix them.")
  4. .addProperty(ReasonerVocabulary.supportsP, RDFS.subClassOf)
  5. .addProperty(ReasonerVocabulary.supportsP, RDFS.subPropertyOf)
  6. .addProperty(ReasonerVocabulary.supportsP, RDFS.member)
  7. .addProperty(ReasonerVocabulary.supportsP, RDFS.range)
  8. .addProperty(ReasonerVocabulary.supportsP, RDFS.domain)
  9. .addProperty(ReasonerVocabulary.versionP, "0.1");

说明jena对其提供了支持。

subPropertyOf
如果张三养了一只狗,那么一定可以推理出张三养了一只宠物,因此养狗和有宠物是subPropertyOf关系。

  1. String ns = "htpp://www.crabone.com#";
  2.  
  3. Model model = ModelFactory.createDefaultModel();
  4.  
  5. // 养狗subPropertyOf有宠物
  6. Property hasPet = model.createProperty(ns, "有宠物");
  7. Property hasDog = model.createProperty(ns, "养狗");
  8. model.add(hasDog, RDFS.subPropertyOf, hasPet);
  9.  
  10. // 张三养了一只狗叫汪汪
  11. model.createResource(ns+"张三").addProperty(hasDog, "汪汪");
  12.  
  13. // 得到JENA内置的RDFS推理机
  14. Reasoner reasoner = ReasonerRegistry.getRDFSReasoner();
  15.  
  16. // 用原来的图和推理机构造出新的推理图
  17. InfModel infModel = ModelFactory.createInfModel(reasoner, model);
  18.  
  19. System.out.println(infModel.getResource(ns+"张三").getProperty(hasPet));

输出:[htpp://www.crabone.com#张三, htpp://www.crabone.com#有宠物, "汪汪"]
从代码来看,jena的推理是基于图的相关算法来实现的。subClassOf和其道理一样,这里就不啰嗦了。

domain、range

个人感觉这是推理性非常强的一种机制!在protege入门里面就有相关的解释。domain和range是用来描述一个property的,比如:拿养狗这个property来说,一般,只有人才会养狗,水瓶是不会养狗的,电插座也是不会养狗的,所以养狗这个property的domain是(一种class),同样养狗这个property的range是(一种class)。当推理机知道这些道理后,告诉它,张三养了一只汪汪,那么,这个推理机能推理出,张三是人,汪汪是狗。

  1. String ns = "htpp://www.crabone.com#";
  2.  
  3. Model model = ModelFactory.createDefaultModel();
  4.  
  5. // 构造人这个类
  6. Resource personClass = model.createResource(ns+"");
  7. model.add(personClass, RDF.type, RDFS.Class);
  8.  
  9. // 构造狗这个类
  10. Resource dogClass = model.createResource(ns+"");
  11. model.add(dogClass, RDF.type, RDFS.Class);
  12.  
  13. // 构造养狗这个属性,并设置domain是人,range是狗
  14. Property hasDog = model.createProperty(ns, "养狗");
  15. model.add(hasDog, RDFS.domain, personClass);
  16. model.add(hasDog, RDFS.range, dogClass);
  17.  
  18. // 添加张三养了一条狗汪汪这个事实
  19. Resource zhangsan = model.createResource(ns+"张三");
  20. Resource wangwang = model.createResource(ns+"汪汪");
  21. zhangsan.addProperty(hasDog, wangwang);
  22.  
  23. // 构造RDFS推理机
  24. Reasoner reasoner = ReasonerRegistry.getRDFSReasoner();
  25.  
  26. // 生成推理图
  27. InfModel infModel = ModelFactory.createInfModel(reasoner, model);
  28.  
  29. System.out.println(infModel.getResource(ns+"张三").getProperty(RDF.type));
  30. System.out.println(infModel.getResource(ns+"汪汪").getProperty(RDF.type));

输出:
[htpp://www.crabone.com#张三, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, htpp://www.crabone.com#人]
[htpp://www.crabone.com#汪汪, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, htpp://www.crabone.com#狗]
总结:domain和rang其实也是一种property;domain这个property用来连接property和class,range这个property用来连接property和class,这是w3的标准,其实在JENA里面比较宽松,domain这个property用来连接property和节点即可,range也是如此。

JENA, 语义网基础

用jena api来理解RDF——三元组

2010年1月1日

JENA中有一个最底层的接口:RDFNode,它代表RDF这张巨大图中的节点,这个节点可以是一个资源,可以是一个字符窜或者数字。因此它对应与2个子接口:
interface Literal extends RDFNode
interface Resource extends RDFNode
Literal接口代表了一些原始类型节点,比如:32位整型、布尔型等等。
Resource接口还可以继续衍生出2个重要的接口:
interface Container extends Resource
interface Property extends Resource
Container接口就对应了RDF的容器表达能力,里面有bag,seq,alt
Property接口就是所谓的资源属性了

在RDF的世界中,其实描述资源只有一种方式,那就是三元组,包括:主体(subject),谓词(predicate),客体(object)。主体和客体就是图中的2个节点,谓词就是一条边。这三元组在JENA中用Statement接口来描述,该接口中有下面3个方法:
public Resource getSubject();
public Property getPredicate();
public RDFNode getObject();

我们可以发现,主体一定是一种资源,不可能是一个Literal原始类型,因此主体必定属于Resource接口实现,但是客体可以是原始类型,比如:人有2条腿。为主体;为谓词;2为客体。

用一个例子来巩固下:

  1. <?xml version="1.0"?>
  2.  <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  3.           xmlns:s="http://example.org/students/vocab#">
  4.  
  5.     <rdf:Description rdf:about="http://example.org/courses/6.001">
  6.        <s:students>
  7.           <rdf:Bag>
  8.              <rdf:li rdf:resource="http://example.org/students/Amy"/>
  9.              <rdf:li rdf:resource="http://example.org/students/Mohamed"/>
  10.              <rdf:li rdf:resource="http://example.org/students/Johann"/>
  11.              <rdf:li rdf:resource="http://example.org/students/Maria"/>
  12.              <rdf:li rdf:resource="http://example.org/students/Phuong"/>
  13.           </rdf:Bag>
  14.        </s:students>
  15.     </rdf:Description>
  16.  </rdf:RDF>

如果要一下子看出这个RDF中有几个三元组,一定不是很方便吧?如果用图来表示:
201001011021
是不是非常清晰呢?图中有一个主体http://example.org/courses/6.001,它有一条边http://example.org/students/vocab#students,对应的客体就是那个空节点。同理还有这个空节点所对应的那些三元组。用JENA来解析这个例子:

  1. Model model = ModelFactory.createDefaultModel();
  2.  
  3. model.read(new FileInputStream("student.rdf"), null);
  4.  
  5. StmtIterator  it = model.listStatements();
  6.  
  7. while(it.hasNext())
  8. {
  9.     System.out.println(it.next());
  10. }

打印的结果如下:
[http://example.org/courses/6.001, http://example.org/students/vocab#students, -23ba78ea:125e9da42c8:-8000]
[-23ba78ea:125e9da42c8:-8000, http://www.w3.org/1999/02/22-rdf-syntax-ns#_5, http://example.org/students/Phuong]
[-23ba78ea:125e9da42c8:-8000, http://www.w3.org/1999/02/22-rdf-syntax-ns#_4, http://example.org/students/Maria]
[-23ba78ea:125e9da42c8:-8000, http://www.w3.org/1999/02/22-rdf-syntax-ns#_3, http://example.org/students/Johann]
[-23ba78ea:125e9da42c8:-8000, http://www.w3.org/1999/02/22-rdf-syntax-ns#_2, http://example.org/students/Mohamed]
[-23ba78ea:125e9da42c8:-8000, http://www.w3.org/1999/02/22-rdf-syntax-ns#_1, http://example.org/students/Amy]
[-23ba78ea:125e9da42c8:-8000, http://www.w3.org/1999/02/22-rdf-syntax-ns#type, http://www.w3.org/1999/02/22-rdf-syntax-ns#Bag]

JENA, 语义网基础 ,

用jena api来理解RDF——空节点

2009年12月26日

在RDF入门的例子中,有这样一幅图:
200912262132
最中间的那个节点起一个过渡作用,这时,虽然它也是一个资源,但这个资源没有必要标上资源描述符,因为它可能只在应用程序局部使用,作为推理机的一个桥梁等等作用,换句说,这个资源别人没有必要去引用。这样的节点,我们称之为空节点:

  1. Model model = ModelFactory.createDefaultModel();
  2.  
  3.   Resource blankNode = model.createResource(new AnonId("tempNode"));
  4.   Property city = model.createProperty("http://www.crabobe.com/city");
  5.   Property street = model.createProperty("http://www.crabobe.com/street");
  6.   blankNode.addProperty(city, "深圳");
  7.   blankNode.addProperty(street, "龙岗");
  8.  
  9.   Resource crab = model.createResource("http://www.crabobe.com/crab");
  10.   Property address = model.createProperty("http://www.crabobe.com/address");
  11.   crab.addProperty(address, blankNode);
  12.  
  13.   model.write(System.out);

注意,包含中文的源码文件必须是UTF-8的,运行结果如下:

  1. <rdf:RDF
  2.     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  3.     xmlns:j.0="http://www.crabobe.com/" > 
  4.   <rdf:Description rdf:about="http://www.crabobe.com/crab">
  5.     <j.0:address rdf:nodeID="A0"/>
  6.   </rdf:Description>
  7.   <rdf:Description rdf:nodeID="A0">
  8.     <j.0:street>龙岗</j.0:street>
  9.     <j.0:city>深圳</j.0:city>
  10.   </rdf:Description>
  11. </rdf:RDF>

JENA, 语义网基础 , , ,