以文本方式查看主题

-  W3CHINA.ORG讨论区 - 语义网·描述逻辑·本体·RDF·OWL  (http://bbs.xml.org.cn/index.asp)
--  『 Semantic Web(语义Web)/描述逻辑/本体 』  (http://bbs.xml.org.cn/list.asp?boardid=2)
----  sparql查询求助  (http://bbs.xml.org.cn/dispbbs.asp?boardid=2&rootid=&id=75706)


--  作者:szm
--  发布时间:6/24/2009 5:14:00 PM

--  sparql查询求助
我按照资料上做了一下本体的简单查询,可是最后出来的结果很奇怪,现将代码贴出来,希望走过路过的人能帮帮我,谢谢!
 Model m = ModelFactory.createOntologyModel();
 try{
     FileInputStream file;
     file = new FileInputStream("E:\\1.owl");
     InputStreamReader in;
     in = new InputStreamReader(file,"UTF-8");
     m.read(in,null);
     in.close();
     }catch(FileNotFoundException e){
        e.printStackTrace();
     }catch(UnsupportedEncodingException e){
        e.printStackTrace();
     }catch(IOException e){
        e.printStackTrace();
     }
 String queryString=
 "PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>"+
 "PREFIX owl:<http://www.w3.org/2002/07/owl#>"+
 "PREFIX eg:<http://www.owl-ontologies.com/unnamed.owl#>"+
 "PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>"+
 "PREFIX xsd:<http://www.w3.org/2001/XMLSchema#string>"+
 "SELECT ?x"+
 "WHERE {"+
 "?x rdfs:subClassOf eg:ManagementScience."+
 "}";
 
 Query query=QueryFactory.create(queryString);
 QueryExecution qexec=QueryExecutionFactory.create(query,m);
 ResultSet rs=qexec.execSelect();
 ResultSetFormatter.out(System.out,rs,query);
 qexec.close();
  %>
</body>
</html>
最后的结果却是:
----------
| xWHERE |
==========
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
|        |
----------
想不通,首先为什么名称不是x,而是xwhere;其次还有一个问题,就是我想要将结果输出到屏幕上,而不是控制台中,该怎么做呢?
--  作者:yayatu
--  发布时间:6/24/2009 5:19:00 PM

--  
"SELECT ?x"+
"WHERE {"+

   呵呵应该是这里出现了问题,SELECT ?x后面必须有个空格,即改为 "SELECT ?X "

  Try it


--  作者:szm
--  发布时间:6/24/2009 7:25:00 PM

--  
的确是的,非常感谢楼上的。
另:1.如果想把结果直接打印在页面上该怎么做呢?
      2.我现在又遇到一个新问题,那就是在检索实例的数据属性时,只能出现这个属性的值的类型,而不是值。举个例子说:我查找一个叫“张三”的人的身高值,希望它的结果是175cm,可是最终得到的结果却是string,就是他返回的是身高这个值的类型是string型的,不晓得为什么?
望大家帮忙,谢谢!
--  作者:yayatu
--  发布时间:6/24/2009 7:34:00 PM

--  

1.如果想把结果直接打印在页面上该怎么做呢?
   页面? web页面吗?
2. 请贴出你的查询语句。再分析问题


--  作者:szm
--  发布时间:6/24/2009 8:42:00 PM

--  
不好意思,是这样的,代码总体和前面是一样的,就是select那段不同,是这样的:
String queryString=
"PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>"+
"PREFIX owl:<http://www.w3.org/2002/07/owl#>"+
"PREFIX eg:<http://www.owl-ontologies.com/unnamed.owl#>"+
"PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>"+
"PREFIX xsd:<http://www.w3.org/2001/XMLSchema#string>"+
"SELECT ?x "+
"WHERE {"+
"eg:张三 eg:身高 ?x."+
"}";
最后的返回结果是string,而不是175cm
页面指的是web页面。
另:想请教一下sparql语句可以动态生成吗?就是具体的查询条件能根据用户提交来确定吗?拿我现在的举个例子就是如果“张三”这个值不是由我预先填好的,而是根据用户提交的结果来绑定的,能实现吗?
谢谢帮助!

--  作者:yayatu
--  发布时间:6/24/2009 9:20:00 PM

--  
1. 打印在页面上的话,你需要用一个Bean来访问查询结果,然后通过Java Bean将结果生成在页面上,这个需要JSP的技术。

2. “身高”在你的本体里面是一个属性吗?

    你自己也可以测试,你查看关于“张三”的的全部信息,你看看有没有这样的三元组
   “张三 eg:身高 175cm”;

   如果可以你把关于张三的信息的那段RDF或者OWL代码发出来。

3. 当然是可以动态生成的,你将为固定的变量作为参数传到函数里面,

    例如 : String name:

   那么 用name这个替换所有张三出现的地方。当然了。这里要注意Java对双引号的处理
   即为 "\ name \"  + eg:身高 +........


--  作者:szm
--  发布时间:6/25/2009 9:42:00 AM

--  
1.我现在也在学习jsp,但还没太入门,关于你说的用Bean访问还不是太明白,不过我会继续学习的;
2.“身高”在我的本体中是一个DataType Property。
   关于这段的代码如下:
  <owl:Class rdf:ID="张三">
    <rdfs:subClassOf>
      <owl:Class rdf:ID="人"/>
    </rdfs:subClassOf>
  </owl:Class>
<owl:DatatypeProperty rdf:ID="身高">
    <rdfs:domain rdf:resource="#人"/>
    <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/>
</owl:DatatypeProperty>
<身高 rdf:datatype="http://www.w3.org/2001/XMLSchema#string"
    >175cm</身高>
麻烦帮我看下,另外我做了三元组的测试,有这样的:张三 eg:身高 “175cm”@en这种形式的三元组,那为什么查不到呢?是不是我的查询表达有错啊?
3.关于动态绑定,我是定义了一个变量来接受值,然后用这个变量替代需要动态绑定的值。
代码如下:
String name=....(动态接受值,已测试,没有问题)
String queryString=
"PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>"+
"PREFIX owl:<http://www.w3.org/2002/07/owl#>"+
"PREFIX eg:<http://www.owl-ontologies.com/unnamed.owl#>"+
"PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>"+
"PREFIX xsd:<http://www.w3.org/2001/XMLSchema#string>"+
"SELECT ?x "+
"WHERE {"+
"?x rdfs:subClassOf " +
name+
"}";
说明:我是这样理解的,应为name作为我定义的变量已经接受了值,它本身是一个变量,而不是一个字符串,所以我认为在select的语句中似乎不需要用引号了吧?那也就不需要转义了,不知道我这样说有没有错
我这个的目的是:比如我的name接收到的值是“人”,那么检索结果就显示“人”的所有子类
4.我现在已经能实现打印到页面了,但是查询三元组时,却报错:
2009-6-25 10:46:09 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet jsp threw exception
java.util.NoSuchElementException
而我把三元关系中设定好一元,也报同样的错,但是如果设定好二元,只查其中一元,就可以正常输出,不知道是什么原因
谢谢!

[此贴子已经被作者于2009-6-25 11:19:35编辑过]

--  作者:yayatu
--  发布时间:6/25/2009 3:46:00 PM

--  
2. 我的查询结果得到了 “175@en“  
  查询语句如下:   
  String qstr = prefixes +
        "SELECT ?h " +
        "WHERE {" +
        "ex:Jone rdf:type ex:Person . " +
        "ex:Jone ex:height ?h ." +
        "}" ;

   其中ex也就是你代码中的eg。只是一个前缀而已。 Jone是我定义的一个人的实例,对应你的张三。

   你再次检查你的查询语句吧

3、是的
4. 从出错信息来看,遇到了空成员异常,也就是说jsp试图去读一个为空的成员。你要检查你的jsp去结果的那段代码,你传给jsp的是几个成员,为你让jsp访问的是几个成员,只有当一致的时候,并且成员值不为空的时候,才不会出错,
  


--  作者:szm
--  发布时间:6/25/2009 4:08:00 PM

--  
谢谢你的解答,可是我又出现了新问题,是这样的:
1.我现在能检索出结果了。但是因为我用的不是你说的通过Bean访问结果然后输出,我暂时还不会,我用的是下面的语句:
while(rs.hasNext()){
   QuerySolution soln=rs.nextSolution();
   String s=soln.get("x").toString();
   StringTokenizer token=new StringTokenizer(s,"#");
   token.nextToken();
   out.print(token.nextToken());
   out.print("
");
                }
问题就出来了,这样的话就只返回string,而用
ResultSetFormatter.out(System.out,rs,query);
就能返回
-----------------------------------------
| x                                     |
=========================================
| "175cm"@en |
-----------------------------------------
请问这是什么原因呢?
另外,前一种方法能返回中文,可后一种遇到中文就乱码;还有那@en就不能删掉吗?
2.关于动态绑定,你也接受我的说法,可是关键是在代码编写中它报错,就是报那个select中name的错,意思是这是一个不被识别的,不知道为什么
谢谢!


--  作者:yayatu
--  发布时间:6/25/2009 5:39:00 PM

--  
1. eclipse打印时候出现的乱码,run-run-common-console encoding- UTF8. 去掉"@"有两种方法,
   a. 在你添加身高175这个值的时候,你就不要选择任何语言。
   
   b. 程序自己处理了。JAVA对字符串的处理。google一下就知道了
2.你需要java提供的双引号的转移。
  
   "?p ex:height \"" + name+ "\". "
--  作者:jpz6311whu
--  发布时间:6/25/2009 8:13:00 PM

--  
楼主还是补一下java基础吧
使用变量name之前,应该先得定义和初始化,这种都是java基础知识
--  作者:szm
--  发布时间:6/26/2009 8:47:00 AM

--  
谢谢楼上的建议,但我也建议你下次发表意见之前先通览一下全贴,我使用的变量是已经定义和初始化过的。
--  作者:szm
--  发布时间:6/26/2009 10:51:00 AM

--  
以下是引用yayatu在2009-6-25 17:39:00的发言:
1. eclipse打印时候出现的乱码,run-run-common-console encoding- UTF8. 去掉"@"有两种方法,
  ......


谢谢你的解答。
关于我之前说到的三元组的问题,我把两种代码都贴出来,麻烦帮我看下:
第一种
 String NL=System.getProperty("line.separator");
 String prefix = "PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>"+"PREFIX owl:<http://www.w3.org/2002/07/owl#>"+"PREFIX eg:<http://www.owl-ontologies.com/unnamed.owl#>"+"PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>"+"PREFIX xsd:<http://www.w3.org/2001/XMLSchema#>";
 String queryString=prefix+NL+"SELECT DISTINCT ?x ?y ?z WHERE {?x ?y ?z}";
 
 Query query=QueryFactory.create(queryString);
 QueryExecution qexec=QueryExecutionFactory.create(query,m);
 ResultSet rs=qexec.execSelect();
 while(rs.hasNext()){
   QuerySolution soln=rs.nextSolution();
   String s=soln.get("x").toString();
   String w=soln.get("y").toString();
                  String c=soln.get("z").toString();
   StringTokenizer token=new StringTokenizer(s,"#");
   StringTokenizer token1=new StringTokenizer(w,"#");
   StringTokenizer token2=new StringTokenizer(c,"#");
   token.nextToken();
   token1.nextToken();
   token2.nextToken();
   out.print(token.nextToken());
   out.print(token1.nextToken());
   out.print(token2.nextToken());
    }
在这种方法下,查询三元组就报之前我说到的空成员的错误,固定其中一元关系也报同样的错,只有三元固定两元才能正常输出(当然我修改了输出的数量,在只输出一元时,我把输出变成了一个变量,而不是现在提供的三个)
第二种
String queryString=
 "PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>"+
 "PREFIX owl:<http://www.w3.org/2002/07/owl#>"+
 "PREFIX eg:<http://www.owl-ontologies.com/unnamed.owl#>"+
 "PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>"+
 "PREFIX xsd:<http://www.w3.org/2001/XMLSchema#string>"+
 "SELECT ?x ?y ?z"+
 "WHERE {"+
 "?x ?y ?z. "+
 "}";
 
 Query query=QueryFactory.create(queryString);
 QueryExecution qexec=QueryExecutionFactory.create(query,m);
 ResultSet rs=qexec.execSelect();
 ResultSetFormatter.out(System.out,rs,query);
在这种情况下,有结果返回,但是只有x和y变量有值返回,z变量的返回值全为空,不知道什么原因。
另外我想问一下:
1.ResultSetFomatter是控制输出格式的,如果我想修改,可以吗?
2.@en是没有了,可是又多了一个^^xsd,晕死!
谢谢你!
--  作者:Humphrey
--  发布时间:6/26/2009 3:20:00 PM

--  
问题是不是出在本体文件上呢?您使用什么平台运行的SPARQL程序?是Jena还是别的什么。
您的意思是无法做到同时输出全部三元组,因此采用单独输出的方法规避,是这样吧?
--  作者:szm
--  发布时间:6/26/2009 3:48:00 PM

--  
以下是引用Humphrey在2009-6-26 15:20:00的发言:
问题是不是出在本体文件上呢?您使用什么平台运行的SPARQL程序?是Jena还是别的什么。
您的意思是无法做到同时输出全部三元组,因此采用单独输出的方法规避,是这样吧?

我不能确定问题出在哪?现在我就是想先弄明白这两种方法的输出为什么会有这么大差别,因为不管本体有没有问题,都不至于导致一种方法要报错,而另一种方法有输出吧,这是我一直困扰的地方。关于你说我采用单独输出规避,其实也不是,因为单独输出是无法得到我所要的三元关系的,我只是测试问题所以改成单独输出的。
谢谢!


--  作者:yayatu
--  发布时间:7/1/2009 7:47:00 PM

--  
我帖一个我自己用得最多的方法(自己写的,非常简单,但是好用,尤其用在SPARQL查询):
    public static QuerySolution[] ProcessQuery ( Model model,String queryStr)
 {
  LinkedList results = new LinkedList();
  model.enterCriticalSection(Lock.READ);
  
  try{
   Query query = QueryFactory.create(queryStr);
   QueryExecution qexec = null;
   try{
    qexec = QueryExecutionFactory.create(query, model);
    ResultSet resultsSet = qexec.execSelect();
    for (; resultsSet.hasNext() ;)
    {
     QuerySolution soln = resultsSet.nextSolution();
     results.add(soln);
    }
   }finally {
    qexec.close();
   }
  }finally {
   model.leaveCriticalSection() ;
  }
  return (QuerySolution[]) results.toArray(new QuerySolution [results.size()]);  

 }

另外,在应用程序中,调用该方法以后,举例如下:

   public Person[] searchPeople(String pattern, int page) {
  String query = prefixes +
     "SELECT  DISTINCT ?p ?name ?mail ?pic ?phone ?area " +
     "WHERE {" +
     "  ?p rdf:type foaf:Person . " +
     "  ?p foaf:name ?name . " +
     " FILTER regex(?name, \"" + pattern + "\",\"i\")" +
     " OPTIONAL { ?p foaf:mbox ?m } " + 
     " OPTIONAL { ?P geek:has_pic ?pic } " +
     " OPTIONAL {?p foaf:phone ?phone } " +
     " OPTIONAL {?p geek:has_area ?area } " +
     "} " +        
     "ORDER BY ?name ";
  QuerySolution[] results = ProcessQuery(model,query);
  List<Person> people = new ArrayList<Person>();
  if (results != null)
  {
   for (int i=0 ; i< results.length; i++)
   {
    RDFNode node1 = results[i].get("p");
    String uri = (node1 == null)?"": node1.isLiteral() ? results[i].getLiteral("p").getString() : node1.toString();
    RDFNode node2 = results[i].get("name");
    String  name = (node2 == null)?"": node2.isLiteral() ? results[i].getLiteral("name").getString() : node2.toString();     
    RDFNode node3 = results[i].get("m");
    String email = (node3 == null)?"": node3.isLiteral() ? results[i].getLiteral("m").getString() : node3.toString();
    RDFNode node4 = results[i].get("pic");
    String  pic = (node4 == null)?"": node4.isLiteral() ? results[i].getLiteral("pic").getString() : node4.toString();  
    RDFNode node5 = results[i].get("phone");
    String  phone = (node5 == null)?"": node5.isLiteral() ? results[i].getLiteral("phone").getString() : node5.toString();  
    RDFNode node6 = results[i].get("area");
    String area = (node6 == null)?"": node6.isLiteral() ? results[i].getLiteral("area").getString() : node6.toString();  
    if (!people.contains(new Person (uri, name, email, area, phone, pic)))
     people.add(new Person (uri, name, email,area, phone, pic));
    
   }
   
  }
  return people.toArray(new Person[people.size()]);
 }

非常好用,你可以试试

另外最后你没有得到?z变量的原因在于,你的select语句中,?z后面缺少空格。


--  作者:springbird
--  发布时间:10/11/2009 10:56:00 AM

--  
楼主问题解决了吗?我用sparql查询遇到了问题,交流一下好吗?
--  作者:liyuhuan
--  发布时间:1/20/2011 4:02:00 PM

--  楼主好厉害呀我有一个问题希望你解答一下
我用protege生成本体,想用SPARQL查询里面所有的类属性和实例的名字显示出来,查询SPARQL语句怎么写呢?
--  作者:andyneo
--  发布时间:5/20/2011 10:08:00 PM

--  
楼主可否解释一下  所贴代码中的 Person[] 谢谢!
W 3 C h i n a ( since 2003 ) 旗 下 站 点
苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
125.000ms