相信很多人有这样的经历:从一个已经存在的owl文件建立protege项目,总是不能成功,报如下的错误:
java.lang.ClassCastException 或者java.lang.nullPointer
at….后面一大堆java异常,都是protege或jena抛出的异常。

由于protege的抱错机制很糟糕,我们几乎不可能从中看出任何有价值的信息,帮助我们判断到底是owl文件中的什么地方有问题。

这个问题我到网上搜了很长时间,发现从2004年就不断有人问,可是却没有正点的回答。只好痛苦的反复尝试和思考,总算皇天不负苦心人,真的让我捉到了线索,解决了这个问题,从中也小有收获,写来用大家共享。

我所需要导入的是一个描述web service的owl文件,就是用protege的owls插件自动的从wsdl中转化生成的那个owl文件。显然,这个文件要用到owls的四个upper本体,还要用到swrl的本体。这一点从名字空间部分就可以看出:
<rdf:RDF
    xmlns:process=”http://www.daml.org/services/owl-s/1.1/Process.owl#”
    xmlns:list=”http://www.daml.org/services/owl-s/1.1/generic/ObjectList.owl#”
    xmlns:swrl=”http://www.w3.org/2003/11/swrl#”
    xmlns:rdfs=”http://www.w3.org/2000/01/rdf-schema#”
    xmlns:owl=”http://www.w3.org/2002/07/owl#”
    xmlns:expression=”http://www.daml.org/services/owl-s/1.1/generic/Expression.owl#”
    xmlns:service=”http://www.daml.org/services/owl-s/1.1/Service.owl#”
    xmlns:grounding=”http://www.daml.org/services/owl-s/1.1/Grounding.owl#”
    xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”
    xmlns:xsd=”http://www.w3.org/2001/XMLSchema#”
    xmlns=”http://192.168.0.102:8080/axis/owl-s/getConcept.owl#”
    xmlns:daml=”http://www.daml.org/2001/03/daml+oil#”
    xmlns:dc=”http://purl.org/dc/elements/1.1/”
    xmlns:profile=”http://www.daml.org/services/owl-s/1.1/Profile.owl#”
  xml:base=”http://192.168.0.102:8080/axis/owl-s/getConcept.owl#”>

当我用这个owl文件建立protege项目时,就遇到了上面的问题。最后,我在名字空间后面的本体导入部分加了这样的一段话,问题就解决了:
<owl:Ontology rdf:about=””>
  <owl:imports rdf:resource=”http://www.daml.org/services/owl-s/1.1/Grounding.owl” /> 
  <owl:imports rdf:resource=”http://www.daml.org/rules/proposal/swrlb.owl” /> 
  <owl:imports rdf:resource=”http://www.daml.org/rules/proposal/swrl.owl” /> 
  <owl:imports rdf:resource=”http://www.daml.org/services/owl-s/1.1/Profile.owl” /> 
  </owl:Ontology>

为什么呢?这要从protege的实现机制说起。显然,protege首先要根据owl文件在内存中生成OntoModel,那么,这个 OntoModel中到底包含哪些资源(类/属性/实例等)呢?显然,这个owl文件中定义的会包含进来。此外,这个owl文件会依赖一些外部的资源,例如,我定义了Service的实例myService,可是Service类确是在owls upper本体中定义的。因此,必须通过最开始的 imports语句显式的高速Protege,你要把需要的本体中的资源也导入到OntoModel中。否则,大家可以想像,protege需要建立一个 service的实例,但是,却不能在OntoModel中找到Service类,那肯定是会出错的嘛!

通常的一个误解是:既然声明了名字空间,难道protege不能自动找到外部资源吗?答案是否定的!名字空间仅仅是用来和短名合在一起,表示资源的URi(也是全局唯一名字),并不会起到警告Protege在OntoModel中导入相应资源的作用。

在上面的例子中,大家可能还会有疑问:为什么只imports了Profile和Grounding,而没有Service和Process呢?答案在于在Profile中,显式的imports了后面二者。于是,imports的关系就传递了下去。

还有一个问题是:问什么owls插件自动生成的owl文件会有这个问题呢?这是因为这个软件的设计者假设这个owl文件总是作为一个被导入的本体与你的工作owl文件协作的。而在后者中,肯定会导入需要的owls upper本体。正是因为有太多这样的假设,才造成了当前语义web工具之间的兼容性非常不好,给使用者(尤其是初学者)造成了很大不便。

希望这个帖子能给大家一些帮助。此外,大家如果真的要用Protege的话(好像目前这是最好的选择,尽管它有很多缺点),还是要好好搞清楚它的一些特点,否则,的确是很郁闷的。

版权声明:本文为zhxiaomiao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/zhxiaomiao/archive/2009/02/20/1395129.html