All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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