JENA:基于String对象创建一个Statement

时间:2014-08-18 14:04:06

标签: java parsing rdf jena

我必须解析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。在我看来这似乎有点矫枉过正(我测试了大部分测试,例如测试实际上有下一个陈述......)。

你知道一个更好/更简单的方法吗?

亚瑟。

2 个答案:

答案 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"));