@ADAMRETTER                                                                  XQUERY FOR

 WWW.ADAMRETTER.ORG.UK                                                       PROGRAMMERS   

HAS ANYONE
HEARD OF 
XQUERY?











WHAT ABOUT
JSONIQ?

      XQuery IS:


  • XML QUERY LANGUAGE (W3C PR)

  • Declarative & Turing COMPLETE

  • FUNCTIONAL (Strong static/dynamic)

  • Modular (NOT OO)

  • SMALL (118/142 functions)

       XQUERY IS NOT:


  • Written in XML

  • Just about XML

  • Just a Query Language

  • Isolated/Esoteric

  • Finished!

Cool things about XQuery

  • Loves the Web

  • Zero Translation Architecture

  • Monadic

  • Extensible

  • Beautiful / Happy Code






XForms    

  XPath

Neil Armstrong Flickr CC-BY fdecomite

XProc



XSLT

XQuery













XQuery is
FLWORs
all the way down

FLWOR Expressions

for
let
where
order by
return


XQuery 3.0 adds:

group by
sliding window
tumbling window
count

FLWOR EXAMPLE (1 OF 2: SOURCE DATA)

<?xml version="1.0" encoding="UTF-8"?>
<products>
    <product dept="GARDEN">
        <name>20ft Garden Hose</name>
        <cost>10.95</cost>
    </product>
    <product dept="KITCHEN">
        <name>Breville Red Pyramid Kettle</name>
        <cost>24.95</cost>
    </product>
    <product dept="GARDEN">
        <name>Flymo Extreme</name>
        <cost>129.99</cost>
    </product>
</products>

FLWOR EXAMPLE (2 OF 2: QUERY)

for $dept-products in //product
group by $dept := $dept-products/@dept
let $value := sum($dept-products/cost)
count $lines
order by $value descending
return
<department>
    <code>{string($dept)}</code>
    <product-lines>{$lines}</product-lines>
    <stock-value>{$value}</stock-value>
</department>

FLWOR EXAMPLE 2

for $dept-products in //product
group by $dept := $dept-products/@dept
let $value := sum($dept-products/cost)
count $lines
order by $value descending
return
<department>
    <code>{string($dept)}</code>
    <product-lines>{$lines}</product-lines>
    <stock-value>{$value}</stock-value>
    <products>
    {
        $dept-products ! <product>{element()}</product>
    }
    </products>
</department>

What about the
web?

XQuery for HTML5

declare namespace output =
    "http://www.w3.org/2010/xslt-xquery-serialization";

declare option output:method        "html";
declare option output:html-version  "5.0";
declare option output:encoding      "UTF-8";
declare option output:indent        "yes";

<html>
    <head><title>Departmental Report</title></head>
    <body>
    {
        for $dept-products in //product
        group by $dept := $dept-products/@dept
        let $value := sum($dept-products/cost)
        count $lines
        order by $value descending
        return
        
        <div class="department">
            <h2>{string($dept)}</h2>
            <div>Product Lines: <span>{$lines}</span></div>
            <div>Stock Value: <span>{$value}</span></div>
            <ul>
            {
                $dept-products ! <li>{name/text()}
                    Cost: £{cost/text()}</li>
            }
            </ul>
        </div>
    }
    </body>
</html>

XQuery for HTML5 ++ RDFa

declare namespace output =
    "http://www.w3.org/2010/xslt-xquery-serialization";

declare option output:method        "html";
declare option output:html-version  "5.0";
declare option output:encoding      "UTF-8";
declare option output:indent        "yes";

<html version="HTML+RDFa 1.1"
    prefix="dc: http://purl.org/dc/terms/">
    <head profile="http://www.w3.org/1999/xhtml/vocab">
        <title>Departmental Report</title>
        <base href="http://company.com/"/>
        <meta property="dc:creator" href="http://www.adamretter.org.uk/#me"/>
        <meta property="dc:subject" href="http://company.com/departments/"/>
    </head>
    <body>
    {
        for $dept-products in //product
        group by $dept := $dept-products/@dept
        let $value := sum($dept-products/cost)
        count $lines
        order by $value descending
        return
        
        <section class="department" about="#{$dept}" rel="dc:subject">
            <h2>{string($dept)}</h2>
            <div>Product Lines: <span>{$lines}</span></div>
            <div>Stock Value: <span>{$value}</span></div>
            <ul>
            {
                $dept-products !
                  <li vocab="http://rdf.data-vocabulary.org/#" typeof="Product">
                      <span property="name">{name/text()}</span> 
                      Cost: <meta property="currency" content="GBP"/>£ 
                      <span property="price">{cost/text()}</span>
                  </li>
            }
            </ul>
        </section>
    }
    </body>
</html>















Erm...
I don't see
any JSON yet!

JSON, the STANDARD WAY?

declare namespace output =
    "http://www.w3.org/2010/xslt-xquery-serialization";

import module namespace xqjson = "http://xqilla.sourceforge.net/lib/xqjson" at "xqjson.xquery";

declare option output:method    "text";
declare option output:encoding  "UTF-8";

xqjson:serialize-json(
    <json type="array">
    {
        for $dept-products in //product
        group by $dept := $dept-products/@dept
        return
        <pair name="department" type="object">
            <pair name="code" type="string">{string($dept)}</pair>
            <pair name="products" type="array">
            {
                $dept-products !
                    <pair name="product" type="object">
                    {
                        element() !
                            <pair name="{local-name(.)}" type="string">{text()}</pair>
                    }
            }
            </pair>
        </pair>
    }
    </json>  
)

JSON, THE EASY WAY*

declare namespace output =
    "http://www.w3.org/2010/xslt-xquery-serialization";

declare option output:method    "json";
declare option output:encoding  "UTF-8";

<departments>
{
    for $dept-products in //product
    group by $dept := $dept-products/@dept
    return
    <department>
        <code>{string($dept)}</code>
        <products>
        {
            $dept-products ! <product>{element()}</product>
        }
        </products>
    </department>
}
</departments>

* XQuery
is only a
specification

Implementations


  • Vary Wildly!

  • W3C Compliance?

  • Indexing and Optimisation

  • Embedded / Standalone / Server / APIs?

  • Extensions / EXQuery / EXPath etc.

Implementations: I/O


  • Initial Document Set (Static Context)?

  • fn:doc() / fn:collection()  / fn:unparsed-text()

  • Update?

  • Side-effects?

  • Expression: Outputs to where?

Implementations


  • C++: XQilla / QtXmlPatterns 

  • Java: JDK / eXist / Saxon

  • Objective C: NSXML

  • SQL/XML: Oracle / DB2 / SQLServer

  • NXD: eXist / BaseX / Marklogic / Zorba

I thought we were
talking about
JSON?

JSONiq

  • XQuery ++ JSON 

  • Extends XDM with JSON types:
    • Atomic: string, integer, decimal, double, boolean, null
    • Item: Array, Object

  • More natural for JScripters: '.' not '/'

  • MongoDB/Couchbase/JDBC

  • See: JSONiq.org / Zorba.io

JSON the JSONiq way

jsoniq version "1.0";

let $products := [
    { dept: "GARDEN", name: "20ft Garden Hose", cost: 10.95 },
    { dept: "KITCHEN", name: "Breville Red Pyramid Kettle", cost: 24.95 },
    { dept: "GARDEN", name: "Flymo Extreme", cost: 129.99 }
] return
    
    for $dept-products in $products()
    group by $dept := $dept-products.dept
    let $value := sum($dept-products.cost)
    count $lines
    order by $value descending
    return
        {
            code: $dept,
            product-lines: $lines,
            stock-value: $value,
            products: $dept-products ! project($$, ("name", "cost"))
        }

STANDARDS STATUS

"You keep using this word, ‘standard’. W3CMemes does not think it means what you think it does."

Standards status


  • XQuery 3.0
    • W3C Proposed Recommendation Oct 2013
    • ...W3C Recommendation... any time now!
    • Several implementations

  • JSONiq 1.0
    • jsoniq.org: 28msec/IBM/Oracle
    • 4 implementations, so far...

  • XQuery 3.1
    • W3C Internal working draft
    • + JSON: Influenced by JSONiq
    • + Map type
    • + More HoF stuff e.g. =>
    • Time frame: 2015
    • Few experimental implementations