Corese News Corese

Sparql & Xpath

Olivier Corby, INRIA, April 2008. See also: Corese

We have introduced an xpath() function that enables to evaluate XPath expressions inside SPARQL queries. This enables to extract additional information from external XML documents of from internal rdf:XMLLiteral data. The xpath() function returns a sequence of datatype values.

 xpath(): XML x Path -> seq(datatype value)
The filter evaluator is extended to process sequences as in XPath. In the example below, we check whether a class and a property have the same label.

select * where {
graph ?g {
  ?c rdf:type rdfs:Class 
  ?c rdfs:label ?label
}
filter(xpath(?g, "/rdf:RDF/rdf:Property/rdfs:label" ) = str(?label))
}

It is possible to reference a SPARQL variable in the XPath expression.

select * where {
graph ?g {
  ?c rdf:type rdfs:Class 
  ?c rdfs:label ?label
}
filter(xpath(?g, "/rdf:RDF/rdf:Property[rdfs:label = $label]" ))
}

It is possible to evaluate an XPath expression on rdf:XMLLiteral data.

select * where {
  ?any c:xmldata ?xml
  filter(datatype(?xml) = rdf:XMLLiteral)
  filter(xpath(?xml, "//*[@id = $any]" ))
}

XPath result can be returned as result of the query.

select * 
xpath(?xml, "//*[@id = $any]/text()") as ?data
where {
  ?any c:xmldata ?xml
  filter(datatype(?xml) = rdf:XMLLiteral)
  filter(xpath(?xml, "//*[@id = $any]" ))
}

XPath result can be reused in another XPath match.

select * 
xpath(?xml, "//*[@id = $any]") as ?obj
xpath(?obj, "name/text()") as ?name
xpath(?obj, "refe/text()") as ?refe
where {
  ?any c:xmldata ?xml
}

Sparql & Xslt

Using the same design pattern, we introduce an xslt() function that enables to process a stylesheet on an XML document (Idea: Adil El Ghali). The result of the function call can be processed using xpath.

 xslt(): XML x XSL -> XML

select * 
xslt(?uri, "style.xsl") as ?doc
xpath(?doc, "//*") as ?res
where {
   ?x c:author ?uri
}

Xslt & Sparql

It is also possible to execute a SPARQL query within XSLT (from function xslt()) with the conventions shown below (Idea & Techno: Fabien Gandon). The result of the query is a DOM tree ready to use in the stylesheet.

 sparql(): Query -> XML/DOM Result

<xsl:stylesheet 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:xalan="http://xml.apache.org/xalan"
xmlns:server="xalan://fr.inria.acacia.corese.Corese"
extension-element-prefixes="server"
>

<xsl:param name='engine' />

<xsl:variable name='query'>
select * where {?x ?p ?y} limit 1
</xsl:variable> 

<xsl:variable name='res'  select='server:sparql($engine, $query)' />

</xsl:stylesheet>

Sparql Nested Query

The sparql() function enables to evaluate a SPARQL query as a filter inside a query. The result is returned as a sequence of sequences of values (one for each variable).

sparql(): Select Query -> seq(seq(datatype value))

sparql(): Ask Query -> xsd:boolean

sparql(): Construct/Describe Query -> rdf:XMLLiteral

The operators are extended to operate on sequences as in XPath, e.g. equality (=) succeeds on a collection if one value of the sequence is equal to the argument.

In the example below, we compute a collection of named graph by an inner query and select the result as ?g. In the query, we compare ?g1 and ?g2 with ?g in such a way to select graphs that are in the collection.

select  * 
sparql(
"select  ?g where { graph ?g {?x c:hasCreated ?doc filter(?x ~ 'olivier' ) }}"
) as ?g
where {
  graph ?g1 {?x c:hasCreated ?doc1}
  graph ?g2 {?x c:hasCreated ?doc2}
  filter(?doc1 != ?doc2)
  filter(?g1 = ?g && ?g2 = ?g)
}

We have added syntactic sugar to enable to compute from (named) graphs using such an inner query. The from (named) clause can be a variable computed by the result of an expression as shown below.

select  * 
sparql(
"select  ?g where { graph ?g {?x c:hasCreated ?doc filter(?x ~ 'olivier' ) }}"
) as ?g
from ?g
where {
  ?x c:hasCreated ?doc1
  ?x c:hasCreated ?doc2
  filter(?doc1 != ?doc2)
}

Sql Nested Query

October 2008

The sql() function enables to evaluate an SQL query as a filter inside a query. The result is returned as a sequence of sequences of values (one for each variable).

prefix db:  <jdbc:derby://localhost:1527/>
select  * 
sql(db:DBTest, 'login', 'passwd',
  'SELECT name, dept FROM employee WHERE age > 18') as (?name, ?dept)
where {
  ?x c:name ?n
  filter(?n = ?name)
}