Search

RDF-based Applications with XQuery

Whilst watching the first few hours of the election coverage, I played with the idea of updating the RDF data for the election. In time I will upload results from a reputable source, but how hard would it be to write an application to capture the results using XQuery and RDF updates directly to the Talis datastore?

Well it turned out to be pretty simple.  The application has four parts:

Model update.

First add a new optional attribute early-vote to the Candidate entity in the model.

A Constituency list. 

A script  to get the list of constituencies to create a page with links to a constituency form. The SPARQL query (minus prefixes) is



select  ?constituency ?name where {
    ?election rdfs:label "UK2010".
    ?election :constituency ?constituency.
    ?constituency rdfs:label ?name


The form script.

A script to generate a form listing the candidates in a constituency.The input to the script  is the constituency URI. The query template is



select ?consname ?cand ?cname ?pname where {
      <constituency> :candidate ?cand; rdfs:label ?consname.
      ?cand rdfs:label ?cname; :party ?party.
      ?party rdfs:label ?pname.
      
}


The string "constituency" is replaced with the input URI before the query is executed and the results turned into tabular XML where each row of the result are the (denormalised) data about a candidate.  The script then generates the form, using the candidate URIs as the field names:



<form action="store-vote.xq" method="get">
     <h2>Return for {$candidates[1]/consname}</h2>
     <table>
     {for $candidate in $candidates
      return 
        <tr>
          <td>{$candidate/cname}</td>
          <td>{$candidate/pname}</td>
          <td><input type="text" name="{$candidate/cand}" size="6"/></td>
        </tr>
     }
    </table>
    <input type="submit" value="Save"/>
  </form>


The update script

A script to generate the RDF and upload to the datastore. The core of this script generates the triples to add the early-votes property to the candidate. 



    for $cand in request:get-parameter-names()
    let $count := request:get-parameter($cand,0)
    return
           element rdf:Description {
              attribute rdf:about  {$cand},  
                element early-votes {
                    attribute rdf:datatype {"http://www.w3.org/2001/XMLSchema#integer" },
                    $count
                }
            }



and the set of these rdf:Descriptions is pushed to the Talis Datastore.

Conclusion

I only put up the first few results e.g. Sutherland Central before realising the futility of the exercise and going to bed.

Of course it's only a hack -no validation, no update confirmation, no staging - but the application is tiny and an hours' work. The key is the use of URIs in the application - I was surprised that using the candidate URIs as form field names actually worked, although POSTing the data caused problems yet to be resolved. Why am I surprised that this match of RDF and XQuery is so good - XQuery (with eXist of course) is a very productive application development tool and a triple store is an ideal data model for this data.