提问人:Abdelghani 提问时间:8/29/2023 更新时间:9/10/2023 访问量:49
org.eclipse.rdf4j.rio.RDFWriter,编写文档时如何设置基本命名空间
org.eclipse.rdf4j.rio.RDFWriter, how to set base namespace when writing document
问:
我正在使用 rdf4j 库导出 xml 文件。 我使用 org.eclipse.rdf4j.rio.RDFWriter 将其保存在文件中,并且需要定义基本命名空间。所以我希望有这样的东西:
<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
xml:base="http://exmaple.org/">
<rdf:Description rdf:about=foo>
<rdf:type rdf:resource= FOO>
...
我知道我可以使用 handleNamespace() 设置命名空间。但是我不知道如何使用它来设置基本命名空间:我试过:
ModelBuilder builder = new ModelBuilder();
ValueFactory vf = SimpleValueFactory.getInstance();
builder.add(vf.createIRI("base:foo"), RDFS.ISDEFINEDBY, vf.createIRI("base:FOO");
Model model = builder.build();
RDFWriter writer = Rio.createWriter(RDFFormat.RDFXML, someOutputStream);
try {
writer.startRDF();
writer.handleNamespace("base", "http://exmaple.org/");
for (Statement st: model) {
writer.handleStatement(st);
}
writer.endRDF();
...
但这并没有给我我所期望的:
<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
xmlns:base="http://exmaple.org/">
<rdf:Description rdf:about=base:foo>
<rdf:type rdf:resource= base:FOO>
有什么想法吗?
答:
命名空间与基本 URI 不是一回事,也没有“基本命名空间”这样的东西。命名空间是 URI 的缩写机制,您可以在其中定义一个前缀,将完整 URI 的第一部分替换为短字符串,以便在 RDF 数据中,您可以使用“前缀名称”表示 URI(具体取决于特定的 RDF 语法)。
另一方面,基本 URI 是一种通用的解析器/编写器机制,允许解析数据中的相对 URI。某些语法格式(如 XML)允许在文档本身中定义基本 URI,而其他语法格式则不允许,但它们的用途与命名空间不同。
例如,以下 XML 代码片段:
<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF
xmlns:base="http://example.org/">
<rdf:Description rdf:about="foo">
....
是合法的 RDF,尽管 RDF/XML 语法规范要求属性(主题)的值是完整的 URI。它合法的原因是定义了一个基本 URI,字符串可以根据该 URI 解析为相对 URI。解析的完整 URI 将为 。请注意,这与命名空间无关。rdf:about
foo
http://example.org/foo
代码中发生的情况是,您根本没有使用基本 URI。在第一部分中,您将在内存中定义一个 RDF 模型,使用 .要将字符串添加为主题 URI。(实际上是 ,但结果是一样的)将其解释为完整的 URI,因为模型构建器中没有定义具有其前缀的命名空间。ModelBuilder
base:foo
ModelBuilder
ValueFactory
base
将该模型写入 XML 文件不会改变这一点,无论您在编写时将什么定义为基本 URI 或命名空间:您正在导出一个具有完整 URI 的 RDF 模型,因此这就是您将在输出中获得的内容。base:foo
若要获得所需的内容,需要确保对象具有完整的 URI,并且在创建编写器时设置其基本 URI,而不是尝试向编写器添加命名空间。Model
var model = new ModelBuilder().add("http://example.org/foo", RDFS.ISDEFINEDBY, "http://example.org/FOO").build();
var writer = Rio.createWriter(RDFFormat.RDFXML, System.out, "http://example.org/");
writer.startRDF();
for (Statement st : model) {
writer.handleStatement(st);
}
writer.endRDF();
...或更简洁地说:
var model = new ModelBuilder().add("http://example.org/foo", RDFS.ISDEFINEDBY, "http://example.org/FOO").build();
Rio.write(model, System.out, "http://example.org/", RDFFormat.RDFXML);
如果您不喜欢在创建模型时每次都编写完整的 URI,那么命名空间可以派上用场,例如:
var model = new ModelBuilder().setNamespace("ex", "http://example.org/")
.add("ex:foo", RDFS.ISDEFINEDBY, "ex:FOO").build();
评论