我有一个人名列表,例如,除了(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 资源。
我使用函数本体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
方法正确地从给定字符串中提取人员,如上面的那些。为了从一个单元格中提取多个人,我这样调用该getPersons
函数subjectMap
:
: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
] .
我使用 RMLMapper https://github.com/RMLio/rmlmapper-java,但是,它只允许为每一行返回一个主题,请参阅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/不兼容,其中说明了以下内容:
它[三元组映射] 必须只有一个主题映射,它指定如何为逻辑源(相应的数据库/CSV/XML/JSON 数据源)的每一行/记录/元素/对象生成主题。
如果我继续添加名字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
为每个主题评估 a 并且现在返回多个主题,所以每个 person 资源都将获得每个人的名字。为了更清楚,它看起来像这样:
: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 的手工提取管道?