【问题标题】:RML Mapping with recursive traversal of nodes with parent attribute appended each time递归遍历节点的 RML 映射,每次都附加父属性
【发布时间】:2021-02-18 16:25:38
【问题描述】:

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

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

在经历了documentationexamplestest cases之后,我不太确定这是否可能。

以下是一个简化的 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>.

感谢您为解决此问题提供的任何帮助。提前致谢!

【问题讨论】:

  • 您可以在 XSLT 中递归连接 names。
  • 您能否给我举个例子或类似的例子?到目前为止,我还没有使用过 XSLT,文档似乎相当广泛。

标签: xml recursion xpath rdf rml-rdf


【解决方案1】:

您可以利用 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 输入示例缺少一些 Children 中间节点的一些 Person 节点。

【讨论】:

  • 感谢您的回复。在您看来,这是否意味着在 RML 中无法获得类似 &lt;http://www.example.com/instance/greatgrandchild1_grandchild1_child1_parent1&gt; 的内容?
  • @swathis 在考虑了更多之后,我意识到可以使用 XPath 的祖先或自我轴和字符串连接函数来解决它。我相应地更新了我的答案。
  • 再次感谢您的修改。我用 RMLMapper 尝试过,似乎既不支持反向轴遍历也不支持字符串连接函数。因此,我将再次尝试使用 CARML 并报告它的进展情况。
猜你喜欢
  • 1970-01-01
  • 2012-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多