RML映射,具有每次附加父属性的节点的递归遍历



我正在尝试将XML源映射到RDF,并想知道如何递归遍历,同时每次都跟踪父级的属性。在所示的示例中,我希望提取所有Person节点,并将每个父节点的name附加到当前节点。考虑所有父名称是必要的,因为节点名称可能不是唯一的。(参见示例中的grandChild1两次(

请注意,我事先不知道嵌套可以达到多少级别,因此为每个级别添加一个TriplesMap是不可行的选择。

在浏览了文档、示例和测试用例之后,我不太确定这是否可能。

以下是一个简化的示例XML、我迄今为止创建的RML映射、使用RMLMapper生成的当前RDF输出,以及我期望的RDF输出。

数据
<Root>
<Person>
<name>parent1</name>
<Children>
<Person>
<name>child1</name>
<Person>
<name>grandchild1</name>
<Children>
<Person>
<name>greatgrandchild1</name>
</Person>
</Children>
</Person>
</Person>
<Person>
<name>child2</name>
<Person>
<name>grandchild1</name>
</Person>
</Person>
</Children>
</Person>
</Root>
映射
@prefix rml: <http://semweb.mmlab.be/ns/rml#> .
@prefix rr: <http://www.w3.org/ns/r2rml#> .
@prefix ql: <http://semweb.mmlab.be/ns/ql#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix testont: <http://www.example.com/ontology/> .
@prefix : <http://www.example.com/rules/> .
@base <http://www.example.com/instance/> .

:TriplesMapPerson a rr:TriplesMap;
rml:logicalSource [
rml:source "recursion_data.xml";
rml:referenceFormulation ql:XPath;
rml:iterator "//Root/Person"
].
:TriplesMapPerson rr:subjectMap [
rr:template "{name}"
].
:TriplesMapPerson rr:predicateObjectMap [
rr:predicate rdf:type;
rr:object testont:Person
].
:TriplesMapChild a rr:TriplesMap;
rml:logicalSource [
rml:source "recursion_data.xml";
rml:referenceFormulation ql:XPath;
rml:iterator "//Root/Person/Children/Person"
].
:TriplesMapChild rr:subjectMap [
rr:template "{name}_{../../name}"
].
:TriplesMapChild rr:predicateObjectMap [
rr:predicate rdf:type;
rr:object testont:Person
].
当前RDF
<http://www.example.com/instance/parent1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.example.com/ontology/Person>.
<http://www.example.com/instance/child1_parent1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.example.com/ontology/Person>.
<http://www.example.com/instance/child2_parent1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.example.com/ontology/Person>.
预期RDF
<http://www.example.com/instance/parent1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.example.com/ontology/Person>.
<http://www.example.com/instance/child1_parent1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.example.com/ontology/Person>.
<http://www.example.com/instance/grandchild1_child1_parent1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.example.com/ontology/Person>.
<http://www.example.com/instance/greatgrandchild1_grandchild1_child1_parent1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.example.com/ontology/Person>.
<http://www.example.com/instance/child2_parent1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.example.com/ontology/Person>.
<http://www.example.com/instance/grandchild1_child2_parent1> <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.example.com/ontology/Person>.

我感谢为解决这一问题提供的任何帮助。提前感谢!

您可以利用XPath的//运算符的递归特性对所有人进行迭代,而不考虑深度。

然后,在主题模板中,您可以使用XPath的祖先或自轴来获得具有名称的祖先节点的列表,将其反转以获得所需的顺序,并获得每个节点的名称属性:

for $ancestor in reverse(ancestor-or-self::*[name]) return $ancestor/name

然后,您可以使用XPaths字符串联接函数来联接值,以获得所需的结果。

然后映射将看起来像

:Person a rr:TriplesMap ;
rml:logicalSource [
rml:source [a carml:Stream ];
rml:referenceFormulation ql:XPath;
rml:iterator "//Person"
] ;
rr:subjectMap [
rr:template "{string-join(for $ancestor in reverse(ancestor-or-self::*[name]) return $ancestor/name, '_')}" ;
rr:class testont:Person ;
] ;
.

给出以下结果:

<http://example.com/base/parent1> a <http://www.example.com/ontology/Person> .
<http://example.com/base/child1_parent1> a <http://www.example.com/ontology/Person> .
<http://example.com/base/grandchild1_child1_parent1> a <http://www.example.com/ontology/Person> .
<http://example.com/base/greatgrandchild1_grandchild1_child1_parent1> a <http://www.example.com/ontology/Person> .
<http://example.com/base/child2_parent1> a <http://www.example.com/ontology/Person> .
<http://example.com/base/grandchild1_child2_parent1> a <http://www.example.com/ontology/Person> .

请注意,为了实现这一点,映射工具的XPath实现需要支持反向轴遍历。我把这个例子讲了一遍https://github.com/carml/carml这支持了这一点。

还要注意,您的xml输入示例缺少某些Person节点的一些中间Children节点。

最新更新