
rdb2rdf.r2rml.xsparql Maven / Gradle / Ivy
(:::::::::::::::::::::::::::::::::::::::)
(: RDB2RDF R2RML processing in XSPARQL :)
(:::::::::::::::::::::::::::::::::::::::)
prefix rr:
prefix foaf:
prefix ex:
prefix xsd:
prefix test:
prefix rdf:
declare variable $r2rml_mapping external ;
declare variable $ds := xsparql:skolemiseGraph($r2rml_mapping);
(: ----------------------------------------------------------- :)
(: ----------------------------------------------AUX FUNCTIONS :)
declare function local:cmp($a, $b) {
data($a) eq fn:concat("http://www.w3.org/ns/r2rml#",$b)
};
(::::::::::::::::::::::::::::::::::::::::::::::::)
(: aux function: create specific types of terms :)
(::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:createTermWithType($value, $type, $lang, $datatype) {
if(local:cmp($type, "IRI"))
then xsparql:createURI($value)
else if(local:cmp($type, "BlankNode"))
then xsparql:createBNode($value)
else if(local:cmp($type, "Literal") or fn:not(fn:empty($lang)) or fn:not(fn:empty($datatype)))
then xsparql:createLiteral($value, $lang, $datatype)
else
xsparql:createTerm($value)
};
(::::::::::::::::::::::::::::::::::::::::::::::::)
(: aux function: create specific types of terms :)
(::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:createTermWithType($value, $type) {
local:createTermWithType($value, $type, "", "")
};
(: retreive all the join conditions specified in a rr:refObjectMap:)
declare function local:getJoins($map) {
for * from $ds
where { $map rr:joinCondition [ rr:child $child; rr:parent $parent ] }
return {data($parent)}
{data($child)}
};
(:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: ----------------------------------------------------------- :)
(: ------------------------------------------ R2RML processing :)
(: Missing / TODO: :)
(: does not perform validation :)
(: defults for termTypes :)
(: 7.7 Inverse Expressions :)
(: build SQL query with join conditions :)
(: capitalisation for table and attribute names :)
(:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(::::::::::::::::::::::::::::)
(: tokenize template string :)
(::::::::::::::::::::::::::::)
declare function local:tokenize($codepoints, $string) {
if (fn:empty($codepoints)) then fn:codepoints-to-string($string)
else if ($codepoints[1] eq 92) then
local:tokenize($codepoints[position()>2], ($string, $codepoints[2]))
else if ($codepoints[1] eq 123) then (: look for 125 :)
(fn:codepoints-to-string($string), local:tokenize($codepoints[position()>1], ()))
else if ($codepoints[1] eq 125) then (: found 125, replace :)
(fn:codepoints-to-string($string), local:tokenize($codepoints[position()>1], ()))
else local:tokenize($codepoints[position()>1], ($string, $codepoints[1]))
};
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: replace enclosed { fields } with their value from the RDB in a template string :)
(: doesn't handle escape chars \{ and \} :)
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:parseTemplate($spec, $row, $type) {
fn:string-join(
(: for $tok at $pos in fn:tokenize($spec, "\{|\}") :)
for $tok at $pos in local:tokenize(fn:string-to-codepoints($spec), ())
return
if (($pos mod 2) eq 0) then
if($type eq "IRI" or fn:empty($type)) then (: assume IRI is the default and encode it :)
fn:encode-for-uri($row//*[@name = $tok]/text()) (: xsparql:value($row, $tok) :)
else
$row/*[@name = $tok]/text()
else
$tok
, "")
};
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: handle foreignKey references :)
(: so far this is done in XQuery! If this becomes a performance issue, build an SQL query with the join conditions, not pretty! :)
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:foreignKey($row, $map) {
for $foreignTable $parentSubject from $ds
where { $map rr:parentTriplesMap $parent .
$parent rr:subjectMap $parentSubject; rr:logicalTable $foreignTable }
return
let $foreignTableResults := local:getLogicalTable($foreignTable)
let $joins := local:getJoins($map) (: get all the join conditions:)
for $foreignRow in $foreignTableResults (: for each row of the foreign table :)
return
(: test if each join condition is satisfied :)
if (every $join in $joins, $join in $joins satisfies $row/*[@name = $join/c]/text() eq $foreignRow/*[@name = $join/p]/text()) then
local:processMap($foreignRow, $parentSubject)
else ()
};
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: creates an RDF term according to the information the mapping file :)
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:createTerm($row, $specType, $specValue, $termType, $lang, $datatype) {
(: let $specType := fn:trace($specType, "specType") return :)
(: let $specValue := fn:trace($specValue, "specValue") return :)
if(local:cmp($specType, "template")) then
let $template := local:parseTemplate($specValue, $row, $termType) return local:createTermWithType($template, $termType, $lang, $datatype)
else if(local:cmp($specType, "subject")) then
local:createTermWithType($specValue, $termType, $lang, $datatype)
else if(local:cmp($specType, "predicate")) then
local:createTermWithType($specValue, fn:concat("http://www.w3.org/ns/r2rml#", "IRI"))
else if(local:cmp($specType, "object")) then
local:createTermWithType($specValue, $termType, $lang, $datatype)
else if(local:cmp($specType, "column")) then
local:createTermWithType($row/*[@name = $specValue]/text(), $termType, $lang, $datatype)
else if(local:cmp($specType, "constant")) then
local:createTermWithType($specValue, $termType, $lang, $datatype)
else if(local:cmp($specType, "graph")) then
if (local:cmp($specValue,"defaultGraph")) then () else local:createTermWithType($specValue, fn:concat("http://www.w3.org/ns/r2rml#", "IRI"))
else ()
};
declare function local:createTerm($specType, $specValue) {
local:createTerm((), $specType, $specValue, (), (), ())
};
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: this function is equivalent to processing an rr:termMap :)
(: creates an RDF term according to the information specified in the mapping file :)
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:processMap($row, $term) {
if ($term) then
for * from $ds
where { $term $specType $specValue .
optional { $term rr:termType $termType }
optional { $term rr:language $lang }
optional { $term rr:datatype $datatype }
filter ($specType != "rr:termType" && $specType != "rr:language" && $specType != "rr:datatype" && $specType != "rr:graphMap" )
}
return
local:createTerm($row, $specType, $specValue, $termType, $lang, $datatype)
else ()
};
(:::::::::::::::::::::::::::::::::::::::::::::)
(: collect all tuples from the logical table :)
(:::::::::::::::::::::::::::::::::::::::::::::)
declare function local:getLogicalTable($table) {
for * from $ds
where {
{ $table rr:tableName $tableName . }
union { $table rr:sqlQuery $sql . optional { $map rr:sqlVersion $sqlVersion }}
}
return
if (fn:empty($sql)) then (: rr:tableName specified :)
(: logical table specified in the mapping file :)
for row $row from $tableName
return $row
else
(: logical table given as an SQL query :)
for row $row from sqlQuery($sql)
return $row
};
(:::::::::::::::::::::::::::::::::::::::)
(: check for object shortcut notations :)
(:::::::::::::::::::::::::::::::::::::::)
declare function local:createObject($row, $po) {
for * from $ds
where { optional { $po rr:object $o } .
optional { $po rr:objectMap $om } .
optional { $po rr:refObjectMap $ref } .
}
return
if ($ref) then local:foreignKey($row, $ref) else
if ($o) then local:createTerm("http://www.w3.org/ns/r2rml#constant", $o) else
local:processMap($row, $om)
};
(::::::::::::::::::::::::::::::::::::::::::)
(: check for predicate shortcut notations :)
(::::::::::::::::::::::::::::::::::::::::::)
declare function local:createPredicate($row, $po) {
for * from $ds
where { optional { $po rr:predicateMap $pm } .
optional { $po rr:predicate $p } .
}
return
if ($pm) then local:processMap($row, $pm)
else local:createTerm("http://www.w3.org/ns/r2rml#constant", $p)
};
(::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: This function processes each rr:predicateObjectMap :)
(::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:createPO($row, $map, $subject, $graph) {
for * from $ds
where { $map rr:predicateObjectMap $po. }
return
let $predicate := local:createPredicate($row, $po) (: check different syntax for predicates :)
let $object := local:createObject($row, $po) (: and objects (also for foreign keys) :)
construct { $subject <{$predicate}> $object <{$graph}> }
(: return {$subject}{$predicate}
{$object}
:)
};
(::::::::::::::::::::::::::::::::::::::)
(: check for graph shortcut notations :)
(::::::::::::::::::::::::::::::::::::::)
declare function local:createGraph($row, $s) {
for * from $ds
where { optional { $s rr:graphMap $graphNode } .
optional { $s rr:graph $g } .
}
return
if ($graphNode) then local:processMap($row, $graphNode) (: determine the graph in which to create the triples :)
else local:createTerm("http://www.w3.org/ns/r2rml#constant", $g)
};
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
(: Given a specific TriplesMap, this function gets the rows from the logical table :)
(: and, for each row creates the triples :)
(::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::)
declare function local:createSPO($map) {
for * from $ds
where { $map a rr:TriplesMap;
rr:logicalTable $table .
optional { $map rr:subjectMap $sm . optional { $sm rr:class $class } . }
optional { $map rr:subject $s . }
}
return
let $rows := local:getLogicalTable($table)
for $row in $rows (: iterates over the sequence returned by local:getLogicalTable :)
let $subject := if ($sm) then local:processMap($row, $sm) (: create subject :)
else local:createTerm("http://www.w3.org/ns/r2rml#constant", $s)
let $graph := local:createGraph($row, $sm) (: determine the graph in which to create the triples :)
construct { $subject rdf:type $class <{$graph}> .
{ local:createPO($row, $map, $subject, $graph) } }
(: return local:createPO($row, $map, $subject, $graph) :)
};
(::::::::::::::::::::::::::::::::::::::)
(: Let's start, iterate over mappings :)
(::::::::::::::::::::::::::::::::::::::)
for * from $ds
where { $map a rr:TriplesMap }
return local:createSPO($map)
© 2015 - 2025 Weber Informatics LLC | Privacy Policy