【问题标题】:How to configure RDF4J Rio writer to write IRIs with special characters?如何配置 RDF4J Rio 编写器以编写带有特殊字符的 IRI?
【发布时间】:2021-07-11 11:11:00
【问题描述】:

我想用rdf/turtle 格式写一个rdf4j.model.Model。该模型应包含带有字符 {} 的 IRI。

当我尝试用rdf4j.rio.Rio 编写RDF 模型时,{} 字符被写为%7B%7D。有没有办法克服这个问题?例如使用path and query variables 创建rdf4j.model.IRI 或配置编写器以保留{} 字符?

我正在使用org.eclipse.rdf4j:rdf4j-runtime:3.6.2

一个例子 sn-p:

import org.eclipse.rdf4j.model.BNode;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Model;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.model.util.ModelBuilder;
import org.eclipse.rdf4j.rio.*;
import org.eclipse.rdf4j.rio.helpers.BasicWriterSettings;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;

public class ExamplePathVariable {

    private final static Logger LOG = Logger.getLogger(ExamplePathVariable.class.getCanonicalName());
    public static void main(String[] args) {

        SimpleValueFactory rdf = SimpleValueFactory.getInstance();
        ModelBuilder modelBuilder = new ModelBuilder();

        BNode subject = rdf.createBNode();
        IRI predicate = rdf.createIRI("http://example.org/onto#hasURI");

        // IRI with special characters !
        IRI object = rdf.createIRI("http://example.org/{token}");

        modelBuilder.add(subject, predicate, object);

        String turtleStr = writeToString(RDFFormat.TURTLE, modelBuilder.build());
        LOG.log(Level.INFO, turtleStr);
    }

    static String writeToString(RDFFormat format, Model model) {
        OutputStream out = new ByteArrayOutputStream();

        try {
            Rio.write(model, out, format,
                    new WriterConfig().set(BasicWriterSettings.INLINE_BLANK_NODES, true));
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                LOG.log(Level.WARNING, e.getMessage());
            }
        }

        return out.toString();
    }
}

这是我得到的:

INFO: 
[] <http://example.org/onto#hasURI> <http://example.org/%7Btoken%7D> .

【问题讨论】:

  • 我不知道你在这里做什么,但我可以告诉你,你得到的 URI 包含正确编码的那些花括号,所以它们 是 i> 可能会被保留。
  • 谢谢,它们正在被保存,如果 Rio 解析器在读取包含 http://example.org/%7Btoken%7D 的海龟文件时可以将 %7B, %7D 视为 {,} 则不会有问题(至少在封闭的应用程序中)。但由于情况并非如此(至少在没有配置 Rio 解析器的知识的情况下),我仍在寻找一种方法来生成实际显示字符 {,} 的 .ttl 文件。我可以手动进行替换,但我想知道是否有通过 rdf4j 更优雅的方式。
  • 另外,如果问题不是很清楚,我很抱歉。如果我可以提供更多信息,我很乐意提供。例如,在NTriplesWriterSettings 上有一个ESCAPE_UNICODE 设置。但是TurtleWriterBasicWriter 都没有这样的设置。
  • > 如果 Rio 解析器在读取海龟文件时可以将 %7B, %7D 视为 {,}

标签: java rdf4j


【解决方案1】:

没有简单的方法来做你想做的事,因为这会导致 Turtle 中的 URI 表示在语法上无效。

字符“{”和“}”,即使它们实际上不是 URI 中的保留字符,也不允许在 URI 中以未编码的形式存在(请参阅https://datatracker.ietf.org/doc/html/rfc3987)。合法地对它们进行序列化的唯一方法是对它们进行百分比编码。

顺便说一下这段代码的唯一原因:

IRI object = rdf.createIRI("http://example.org/{token}");

成功之处在于您使用的SimpleValueFactory 不进行字符验证(出于性能原因)。如果您改用recommended approach(自RDF4J 3.5 起)使用Values 静态工厂:

IRI object = Values.iri("http://example.org/{token}");

...您会立即收到验证错误。

如果你想输入一个事先不知道它是否会包含任何无效字符的字符串,并想尽最大努力将其转换为合法的 URI,你可以使用ParsedIRI.create

IRI object = Values.iri(ParsedIRI.create("http://example.org/{token}").toString());

【讨论】:

  • 非常感谢。我真的很困惑,因为我期望这些字符不需要进行 % 编码,因为这是一个 IRI(而不仅仅是任何 URI)。我应该搜索支持 URI 模板的库。
猜你喜欢
  • 1970-01-01
  • 2013-04-15
  • 2017-09-12
  • 2021-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多