Jena3上传Virtuoso时如何避免显式发布字符串数据类型?
这个问题我之前也碰到过,核心是Jena默认的字符串属性添加方式会显式带上xsd:string数据类型,而通过RDF文件上传时序列化器会省略这个默认类型,导致Virtuoso存储后的查询结果表现不同。下面给你几个可行的解决办法:
1. 手动创建无类型的字面量
不要直接使用addProperty(String, String)方法,而是先创建不带数据类型的字面量,再添加属性。Jena的model.createLiteral(String value)方法会生成没有数据类型也没有语言标签的简单字面量,上传到Virtuoso后就不会显式带上xsd:string:
// 先定义你的属性(替换成实际的属性URI) Property targetProp = model.createProperty("http://your-ontology/your-property"); // 创建无类型字面量 Literal stringLiteral = model.createLiteral("3"); // 给资源添加属性 yourResource.addProperty(targetProp, stringLiteral);
这样处理后,Virtuoso存储的字面量就和你用isql上传RDF文件的结果一致了。
2. 序列化后再上传(模拟isql流程)
先把Jena模型序列化为Turtle格式(Jena的Turtle序列化器默认会省略xsd:string类型,因为这是RDF字面量的默认类型),再通过Virtuoso的API上传序列化后的内容:
// 将模型序列化为Turtle字符串 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); model.write(outputStream, "TURTLE"); String turtleData = outputStream.toString("UTF-8"); // 连接Virtuoso并上传Turtle数据 VirtGraph virtGraph = new VirtGraph("http://your-graph-uri", "jdbc:virtuoso://localhost:1111", "dba", "dba"); virtGraph.read(new ByteArrayInputStream(turtleData.getBytes()), "http://your-base-uri", "TURTLE");
这种方式完全复刻了isql上传RDF文件的逻辑,能保证存储后的字面量不带显式数据类型。
3. 查询时兼容处理(应急方案)
如果暂时没法修改上传代码,可以在SPARQL查询里用STR()函数剥离数据类型,再转成整数:
SELECT (xsd:integer(STR(?result)) AS ?intResult) WHERE { # 你的查询模式 }
这样在Rapidminer里就能直接拿到整数值,不过这是治标不治本的方法,优先推荐前两种从上传端解决的方案。
补充说明
RDF规范里,无类型的字面量默认就是xsd:string类型,但不同工具的表现有差异:Jena为了明确性,默认给addProperty(String, String)生成的字面量加上显式类型;而Turtle序列化器会遵循“默认类型可省略”的规则,所以isql上传后Virtuoso存储的是无类型字面量,查询时就不会显示^^xsd:string。
内容的提问来源于stack exchange,提问作者User 23

