我必须解析N-TRIPLE内容并对给定类型的每个字面值应用修改。
例如,我必须修改每个WKTLiteral以使用参考。三倍如:
"POINT (0.0 0.0)"^^<http://www.opengis.net/ont/geosparql#wktLiteral>
必须成为:
"<http://www.opengis.net/def/crs/EPSG/0/4326> POINT (0.0 0.0)"^^<http://www.opengis.net/ont/geosparql#wktLiteral>
我将每个三行逐行添加到String对象中,并希望从此String创建Jena语句。我的目标是使用Jena解析器来避免一些脏的字符串操作,例如易于出错的分割。
目前,我发现这样做的唯一方法是:
String line = "%a triple is here%";
//Create an empty model
final Model model = ModelFactory.createDefaultModel();
//Parse and store the RDF triple in the model
RDFDataMgr.read(model, new ByteArrayInputStream(line.getBytes(StandardCharsets.UTF_8)), Lang.NTRIPLES);
//Get all the statements - only 1 if any
final StmtIterator listStatements = model.listStatements();
//Got my statement
final Statement statement = listStatements.next();
我还尝试使用RDFReader,但不知道使用RDFOutputStream ...... 要仅从String获取自动创建的Statement对象,我必须创建一个Model,使用Reader和Iterator。在我看来这似乎有点矫枉过正(我测试了大部分测试,例如测试实际上有下一个陈述......)。
你知道一个更好/更简单的方法吗?
亚瑟。
答案 0 :(得分:3)
我不知道你是否找到了比你所拥有的更好的方式,除非你应该阅读文件的块而不是每条线。如果您读取文件的块,则可以使用简单的构造SPARQL查询来转换整个块。这将提供一个新模型,您可以将该模型的N-TRIPLE序列化附加到输出文件(或将其插入新图表等)。假设您已获得此数据:
<urn:ex:a> <urn:ex:p> <urn:ex:b>.
<urn:ex:c> <urn:ex:q> "POINT (0.0 0.0)"^^<http://www.opengis.net/ont/geosparql#wktLiteral>.
然后像这样的查询将产生以下更新的模型:
construct { ?s ?p ?oo }
where {
#-- constant values pulled out for readability; this
#-- is optional, of course.
values (?dt ?prefix) {
(<http://www.opengis.net/ont/geosparql#wktLiteral>
"<http://www.opengis.net/def/crs/EPSG/0/4326> ")
}
#-- grab each triple, and bind ?oo to ?o if it doesn't
#-- need to be updated, or to a new literal, if it does.
?s ?p ?o .
bind( if( isLiteral(?o) && datatype(?o) = ?dt,
strdt( concat(?prefix,str(?o)), ?dt ),
?o )
as ?oo )
}
<urn:ex:a> <urn:ex:p> <urn:ex:b> .
<urn:ex:c> <urn:ex:q> "<http://www.opengis.net/def/crs/EPSG/0/4326> POINT (0.0 0.0)"^^<http://www.opengis.net/ont/geosparql#wktLiteral> .
如果要将整个数据集加载到TDB实例中,可以使用此变量相对轻松地转换整个数据集,然后将最终数据转储到新文件中。
答案 1 :(得分:2)
您会发现使用streams效率更高。 StreamRDF
个实例会在遇到时发送triples个。然后,您可以根据需要重写。
Streams使用jena的SPI级别 - 节点,三元组和四元组而不是语句,资源等 - 这些都缺乏一些优点,但对于像这样的任务,它们是理想的。
根据你所写的内容,我怀疑写出固定的N-Triples是你想要的?这是一个可以做到这一点的例子。它所做的只是1)创建一个输出三元组的流,2)创建一个等待三元组的流,纠正对象(如果需要),并写入结果和3)启动整个解析:
final String wkt = "http://www.opengis.net/ont/geosparql#wktLiteral";
// Stream result to stdout
final StreamRDF outputHandler = StreamRDFLib.writer(System.out);
StreamRDF inputHandler = new StreamRDFBase() {
@Override
public void triple(Triple triple) { // Got a triple
Node object = triple.getObject();
Node transformed;
// if object is literal and has wkt type
if (object.isLiteral() &&
wkt.equals(object.getLiteralDatatypeURI())) {
// Make a new node, suitably modified
transformed = NodeFactory.createLiteral(
"<http://www.opengis.net/def/crs/EPSG/0/4326> "
+ object.getLiteralLexicalForm(),
object.getLiteralDatatype());
} else { // Do nothing
transformed = object;
}
// Write out with corrected object
outputHandler.triple(
Triple.create( triple.getSubject(), triple.getPredicate(),
transformed
));
}
};
// Parse
RDFDataMgr.parse(inputHandler, RDFDataMgr.open("file"));