对于输入的一个数据元素(单元格)中的多个复杂实体,在不清理输入数据的情况下,RML 是否有解决方案?

Is there a solution in RML for multiple complex entities in one data element (cell) of the input without cleaning the input data?

我有一个人名列表,例如,除了(Person 是列名):

Person
"Wilson, Charles; Harris Arthur"
"White, D.
Arthur Harris"

请注意,提到多个人的方式不同,分隔也不同。

我想使用 RDF 映射语言 https://rml.io/ 创建以下 RDF 而无需清理(或更改)输入数据:

:Wilson a foaf:Person;
    foaf:firstName "Charles";
    foaf:lastName "Wilson" .

:Harris a foaf:Person;
    foaf:firstName "Arthur";
    foaf:lastName "Harris" .

:White a foaf:Person;
    foaf:firstName "D.";
    foaf:lastName "White" .

请注意,Arthur Harris 在输入数据中被提及两次,但只创建了一个 RDF 资源。

我使用函数 ontology https://fno.io/ 并创建了自定义 java 方法。基于参数 mode 返回人员属性列表(例如,仅 URI 或仅名字)。

public static List<String> getPersons(String value, String mode) {
    if(mode == null || value.trim().isEmpty())
        return Arrays.asList();

    List<String> results = new ArrayList<>();
    for(Person p : getAllPersons(value)) {
        if(mode.trim().isEmpty() || mode.equals("URI")) {
            results.add("http://example.org/person/" + p.getLastName());
        } else if(mode.equals("firstName")) {
            results.add(p.getFirstName());
        } else if(mode.equals("lastName")) {
            results.add(p.getLastName());
        } else if(mode.equals("fullName")) {
            results.add(p.getFullName());
        }
    }

    return results;
}

假设 getAllPersons 方法正确地从给定的字符串中提取人物,就像上面的那样。 为了从一个单元格中提取多个人,我在 subjectMap 中调用 getPersons 函数,如下所示:

:tripleMap a rr:TriplesMap .
:tripleMap rml:logicalSource :ExampleSource .
:tripleMap rr:subjectMap [
    fnml:functionValue [

        rr:predicateObjectMap [
            rr:predicate fno:executes ;
            rr:objectMap [ rr:constant cf:getPersons ]
        ] ;
        rr:predicateObjectMap [
            rr:predicate grel:valueParameter ;
            rr:objectMap [ rml:reference "Person" ] # the column name
        ] ;
        rr:predicateObjectMap [
            rr:predicate grel:valueParameter2 ;
            rr:objectMap [ rr:constant "URI" ] # the mode
        ]
    ];
    rr:termType rr:IRI ;
    rr:class foaf:Person
] .

我使用 RLMMapper https://github.com/RMLio/rmlmapper-java, however, it only allows to return one subject for each line, see https://github.com/RMLio/rmlmapper-java/blob/master/src/main/java/be/ugent/rml/Executor.java#L292。 这就是为什么我写了一个 List<ProvenancedTerm> getSubjects(Term triplesMap, Mapping mapping, Record record, int i) 方法并相应地替换它的原因。 这导致以下结果:

:Wilson a foaf:Person .

:Harris a foaf:Person .

:White a foaf:Person .

我知道此扩展与 RML 规范不兼容 https://rml.io/specs/rml/,其中规定如下:

It [a triples map] must have exactly one subject map that specifies how to generate a subject for each row/record/element/object of the logical source (database/CSV/XML/JSON data source accordingly).

如果我继续添加名字 resp。姓,可以添加以下 predicateObjectMap

:tripleMap rr:predicateObjectMap [
    rr:predicate foaf:firstName;
    rr:objectMap [
        fnml:functionValue [

            rr:predicateObjectMap [
                rr:predicate fno:executes ;
                rr:objectMap [ rr:constant cf:getPersons ]
            ] ;
            rr:predicateObjectMap [
                rr:predicate grel:valueParameter ;
                rr:objectMap [ rml:reference "Person" ] # the column name
            ] ;
            rr:predicateObjectMap [
                rr:predicate grel:valueParameter2 ;
                rr:objectMap [ rr:constant "firstName" ] # the mode
            ]
        ]
    ]
] .

因为 predicateObjectMap 对每个主题进行评估,现在返回多个主题,每个人资源将获得每个人的名字。为了更清楚,看起来像这样:

:Wilson a foaf:Person;
    foaf:firstName "Charles" ;
    foaf:firstName "Arthur" ;
    foaf:firstName "D." .

:Harris a foaf:Person;
    foaf:firstName "Charles" ;
    foaf:firstName "Arthur" ;
    foaf:firstName "D." .

:White a foaf:Person;
    foaf:firstName "Charles" ;
    foaf:firstName "Arthur" ;
    foaf:firstName "D." .

我的问题是:在不清理(或更改)输入的情况下,RML 中是否存在针对输入的一个数据元素(单元格)中的多个复杂实体(例如,具有名字和姓氏的人)的解决方案或变通方法数据?

也许这个问题与我的问题有关:https://www.w3.org/community/kg-construct/track/issues/3

如果这样的用例不打算通过像 RML 这样的映射框架来解决,那也很好。如果是这种情况,还有什么替代方案?例如,生成 RDF 的手工提取管道?

据我所知,使用 FnO 函数和连接条件无法实现您的尝试。

但是,您可以尝试指定一个巧妙的 rml:queryrml:iterator,在复数值到达 RLMMapper 之前将其拆分。不过,这是否可能取决于特定的源数据库。

例如,如果源是 SQL 服务器数据库,您可以使用函数 STRING_SPLIT. Or if it is a PostgreSQL database, you could use STRING_TO_ARRAY together with unnest。 (由于数据中使用了不同的分隔符,您可能必须为每个不同的分隔符调用一次 STRING_SPLIT 或 STRING_TO_ARRAY。

如果您提供有关底层数据库的更多信息,我可以用示例更新此答案

(注意:我为 RML 及其技术做出贡献。)

据我了解,您遇到了归一化问题(多值单元格)。当然,您要求的是在 1NF 中拥有一个数据集,请参阅:https://en.wikipedia.org/wiki/First_normal_form

要解决 CSV 文件中这些常见的异质性问题,您可以在 Web 注释(W3C 推荐)上使用 CSV。更详细地说,您在这种情况下要求的 属性 是 csvw:separator (https://www.w3.org/TR/tabular-data-primer/#sequence-values).

但是CSVW的解析器并不多,其属性生成RDF的语义也不是很清楚。我们一直在研究一种与 CSVW 和 RML+FnO 一起工作的解决方案,以从表格数据生成虚拟 KG(还有一个 SPARQL 查询作为输入,而不是将输入数据集转换为 RDF)。我们提议的输出是一个结构良好的数据库,带有标准 [R2]RML 映射,因此任何符合 [R2]RML 的都可以用来回答查询或实现知识图谱。虽然我们目前不支持具体化步骤,但它在我们的 ToDo 列表中。

你可以看一下投稿(正在审核中):http://www.semantic-web-journal.net/content/enhancing-virtual-ontology-based-access-over-tabular-data-morph-csv

网站:https://morph.oeg.fi.upm.es/tool/morph-csv