] > What's new in XQuery 3.0? hello mum"); doc.close(); } // find current slide based upon location // first find target anchor and then look // for associated div element enclosing it // finally map that to slide number function findSlideNumber(uri) { // first get anchor from page location var i = uri.indexOf("#"); // check if anchor is entire page if (i < 0) return 0; // yes var anchor = unescape(uri.substr(i+1)); // now use anchor as XML ID to find target var target = document.getElementById(anchor); if (!target) { // does anchor look like "(2)" for slide 2 ?? // where first slide is (1) var re = /\((\d)+\)/; if (anchor.match(re)) { var num = parseInt(anchor.substring(1, anchor.length-1)); if (num > slides.length) num = 1; if (--num < 0) num = 0; return num; } // accept [2] for backwards compatibility re = /\[(\d)+\]/; if (anchor.match(re)) { var num = parseInt(anchor.substring(1, anchor.length-1)); if (num > slides.length) num = 1; if (--num < 0) num = 0; return num; } // oh dear unknown anchor return 0; } // search for enclosing slide while (true) { // browser coerces html elements to uppercase! if (target.nodeName.toLowerCase() == "div" && hasClass(target, "slide")) { // found the slide element break; } // otherwise try parent element if any target = target.parentNode; if (!target) { return 0; // no luck! } }; for (i = 0; i < slides.length; ++i) { if (slides[i] == target) return i; // success } // oh dear still no luck return 0; } // find slide name from first h1 element // default to document title + slide number function slideName(index) { var name = null; var slide = slides[index]; var heading = findHeading(slide); if (heading) name = extractText(heading); if (!name) name = title + "(" + (index + 1) + ")"; name.replace(/\&/g, "&"); name.replace(/\/g, ">"); return name; } // find first h1 element in DOM tree function findHeading(node) { if (!node || node.nodeType != 1) return null; if (node.nodeName == "H1" || node.nodeName == "h1") return node; var child = node.firstChild; while (child) { node = findHeading(child); if (node) return node; child = child.nextSibling; } return null; } // recursively extract text from DOM tree function extractText(node) { if (!node) return ""; // text nodes if (node.nodeType == 3) return node.nodeValue; // elements if (node.nodeType == 1) { node = node.firstChild; var text = ""; while (node) { text = text + extractText(node); node = node.nextSibling; } return text; } return ""; } // find copyright text from meta element function findCopyright() { var name, content; var meta = document.getElementsByTagName("meta"); for (var i = 0; i < meta.length; ++i) { name = meta[i].getAttribute("name"); content = meta[i].getAttribute("content"); if (name == "copyright") return content; } return null; } function findSizeAdjust() { var name, content, offset; var meta = document.getElementsByTagName("meta"); for (var i = 0; i < meta.length; ++i) { name = meta[i].getAttribute("name"); content = meta[i].getAttribute("content"); if (name == "font-size-adjustment") return 1 * content; } return 1; } function addToolbar() { var slideCounter, page; var toolbar = createElement("div"); toolbar.setAttribute("class", "toolbar"); if (ns_pos) // a reasonably behaved browser { var right = document.createElement("div"); right.setAttribute("style", "float: right; text-align: right"); slideCounter = document.createElement("div") slideCounter.innerHTML = "slide".localize() + " n/m"; right.appendChild(slideCounter); toolbar.appendChild(right); var left = document.createElement("div"); left.setAttribute("style", "text-align: left"); // global end of slide indicator eos = document.createElement("span"); eos.innerHTML = "* "; left.appendChild(eos); var help = document.createElement("a"); help.setAttribute("href", helpPage); help.setAttribute("title", helpText.localize()); help.innerHTML = " ".localize(); left.appendChild(help); helpAnchor = help; // save for focus hack var gap1 = document.createTextNode(" "); left.appendChild(gap1); var contents = document.createElement("a"); contents.setAttribute("href", "javascript:toggleTableOfContents()"); contents.setAttribute("title", "table of contents".localize()); contents.innerHTML = "Table of Contents ".localize(); left.appendChild(contents); var gap2 = document.createTextNode(".............................................."); left.appendChild(gap2); var start = document.createElement("a"); start.setAttribute("href", "javascript:firstSlide()"); start.setAttribute("title", "restart presentation".localize()); start.innerHTML = " ".localize(); // start.setAttribute("href", "javascript:printSlides()"); // start.setAttribute("title", "print all slides".localize()); // start.innerHTML = "print!".localize(); left.appendChild(start); // var identity = document.createTextNode(""); // left.appendChild(identity); var copyright = findCopyright(); if (copyright) { var span = document.createElement("span"); span.innerHTML = copyright; span.style.color = "black"; span.style.marginLeft = "4em"; left.appendChild(span); } toolbar.appendChild(left); } else // IE so need to work around its poor CSS support { toolbar.style.position = (ie7 ? "fixed" : "absolute"); toolbar.style.zIndex = "200"; toolbar.style.width = "99.9%"; toolbar.style.height = "1.2em"; toolbar.style.top = "auto"; toolbar.style.bottom = "0"; toolbar.style.left = "0"; toolbar.style.right = "0"; toolbar.style.textAlign = "left"; toolbar.style.fontSize = "60%"; toolbar.style.color = "red"; toolbar.borderWidth = 0; toolbar.style.background = "rgb(240,240,240)"; // would like to have help text left aligned // and page counter right aligned, floating // div's don't work, so instead use nested // absolutely positioned div's. var sp = document.createElement("span"); sp.innerHTML = "  * "; toolbar.appendChild(sp); eos = sp; // end of slide indicator var help = document.createElement("a"); help.setAttribute("href", helpPage); help.setAttribute("title", helpText.localize()); help.innerHTML = "help?".localize(); toolbar.appendChild(help); helpAnchor = help; // save for focus hack var gap1 = document.createTextNode(" "); toolbar.appendChild(gap1); var contents = document.createElement("a"); contents.setAttribute("href", "javascript:toggleTableOfContents()"); contents.setAttribute("title", "table of contents".localize()); contents.innerHTML = "contents?".localize(); toolbar.appendChild(contents); var gap2 = document.createTextNode(" "); toolbar.appendChild(gap2); var start = document.createElement("a"); start.setAttribute("href", "javascript:firstSlide()"); start.setAttribute("title", "restart presentation".localize()); start.innerHTML = "restart?".localize(); // start.setAttribute("href", "javascript:printSlides()"); // start.setAttribute("title", "print all slides".localize()); // start.innerHTML = "print!".localize(); toolbar.appendChild(start); var copyright = findCopyright(); if (copyright) { var span = document.createElement("span"); span.innerHTML = copyright; span.style.color = "black"; span.style.marginLeft = "2em"; toolbar.appendChild(span); } slideCounter = document.createElement("div") slideCounter.style.position = "absolute"; slideCounter.style.width = "auto"; //"20%"; slideCounter.style.height = "1.2em"; slideCounter.style.top = "auto"; slideCounter.style.bottom = 0; slideCounter.style.right = "0"; slideCounter.style.textAlign = "right"; slideCounter.style.color = "red"; slideCounter.style.background = "rgb(240,240,240)"; slideCounter.innerHTML = "slide".localize() + " n/m"; toolbar.appendChild(slideCounter); } // ensure that click isn't passed through to the page toolbar.onclick = stopPropagation; document.body.appendChild(toolbar); slideNumElement = slideCounter; setEosStatus(false); return toolbar; } function isShownToc() { if (toc && toc.style.visible == "visible") return true; return false; } function showTableOfContents() { if (toc) { if (toc.style.visibility != "visible") { toc.style.visibility = "visible"; toc.style.display = "block"; toc.focus(); if (ie7 && slidenum == 0) setTimeout("ieHack()", 100); } else hideTableOfContents(); } } function hideTableOfContents() { if (toc && toc.style.visibility != "hidden") { toc.style.visibility = "hidden"; toc.style.display = "none"; try { if (!opera) helpAnchor.focus(); } catch (e) { } } } function toggleTableOfContents() { if (toc) { if (toc.style.visible != "visible") showTableOfContents(); else hideTableOfContents(); } } // called on clicking toc entry function gotoEntry(e) { var target; if (!e) var e = window.event; if (e.target) target = e.target; else if (e.srcElement) target = e.srcElement; // work around Safari bug if (target.nodeType == 3) target = target.parentNode; if (target && target.nodeType == 1) { var uri = target.getAttribute("href"); if (uri) { //alert("going to " + uri); var slide = slides[slidenum]; hideSlide(slide); slidenum = findSlideNumber(uri); slide = slides[slidenum]; lastShown = null; setLocation(); setVisibilityAllIncremental("hidden"); setEosStatus(!nextIncrementalItem(lastShown)); showSlide(slide); //target.focus(); try { if (!opera) helpAnchor.focus(); } catch (e) { } } } hideTableOfContents(e); if (ie7) ieHack(); stopPropagation(e); return cancel(e); } // called onkeydown for toc entry function gotoTocEntry(event) { var key; if (!event) var event = window.event; // kludge around NS/IE differences if (window.event) key = window.event.keyCode; else if (event.which) key = event.which; else return true; // Yikes! unknown browser // ignore event if key value is zero // as for alt on Opera and Konqueror if (!key) return true; // check for concurrent control/command/alt key // but are these only present on mouse events? if (event.ctrlKey || event.altKey) return true; if (key == 13) { var uri = this.getAttribute("href"); if (uri) { //alert("going to " + uri); var slide = slides[slidenum]; hideSlide(slide); slidenum = findSlideNumber(uri); slide = slides[slidenum]; lastShown = null; setLocation(); setVisibilityAllIncremental("hidden"); setEosStatus(!nextIncrementalItem(lastShown)); showSlide(slide); //target.focus(); try { if (!opera) helpAnchor.focus(); } catch (e) { } } hideTableOfContents(); if (ie7) ieHack(); return cancel(event); } if (key == 40 && this.next) { this.next.focus(); return cancel(event); } if (key == 38 && this.previous) { this.previous.focus(); return cancel(event); } return true; } function isTitleSlide(slide) { return hasClass(slide, "title"); } // create div element with links to each slide function tableOfContents() { var toc = document.createElement("div"); addClass(toc, "toc"); //toc.setAttribute("tabindex", "0"); var heading = document.createElement("div"); addClass(heading, "toc-heading"); heading.innerHTML = "Table of Contents".localize(); heading.style.textAlign = "center"; heading.style.width = "100%"; heading.style.margin = "0"; heading.style.marginBottom = "1em"; heading.style.borderBottomStyle = "solid"; heading.style.borderBottomColor = "rgb(180,180,180)"; heading.style.borderBottomWidth = "1px"; toc.appendChild(heading); var previous = null; for (var i = 0; i < slides.length; ++i) { var title = hasClass(slides[i], "title"); var num = document.createTextNode((i + 1) + ". "); toc.appendChild(num); var a = document.createElement("a"); a.setAttribute("href", "#(" + (i+1) + ")"); if (title) addClass(a, "titleslide"); var name = document.createTextNode(slideName(i)); a.appendChild(name); a.onclick = gotoEntry; a.onkeydown = gotoTocEntry; a.previous = previous; if (previous) previous.next = a; toc.appendChild(a); if (i == 0) toc.first = a; if (i < slides.length - 1) { var br = document.createElement("br"); toc.appendChild(br); } previous = a; } toc.focus = function () { if (this.first) this.first.focus(); } toc.onmouseup = mouseButtonUp; toc.onclick = function (e) { e||(e=window.event); if (selectedTextLen <= 0) hideTableOfContents(); stopPropagation(e); if (e.cancel != undefined) e.cancel = true; if (e.returnValue != undefined) e.returnValue = false; return false; }; toc.style.position = "absolute"; toc.style.zIndex = "300"; toc.style.width = "60%"; toc.style.maxWidth = "30em"; toc.style.height = "30em"; toc.style.overflow = "auto"; toc.style.top = "auto"; toc.style.right = "auto"; toc.style.left = "4em"; toc.style.bottom = "4em"; toc.style.padding = "1em"; toc.style.background = "rgb(240,240,240)"; toc.style.borderStyle = "solid"; toc.style.borderWidth = "2px"; toc.style.fontSize = "60%"; document.body.insertBefore(toc, document.body.firstChild); return toc; } function replaceByNonBreakingSpace(str) { for (var i = 0; i < str.length; ++i) str[i] = 160; } function initOutliner() { var items = document.getElementsByTagName("LI"); for (var i = 0; i < items.length; ++i) { var target = items[i]; if (!hasClass(target.parentNode, "outline")) continue; target.onclick = outlineClick; if (!ns_pos) { target.onmouseover = hoverOutline; target.onmouseout = unhoverOutline; } if (foldable(target)) { target.foldable = true; target.onfocus = function () {outline = this;}; target.onblur = function () {outline = null;}; if (!target.getAttribute("tabindex")) target.setAttribute("tabindex", "0"); if (hasClass(target, "expand")) unfold(target); else fold(target); } else { addClass(target, "nofold"); target.visible = true; target.foldable = false; } } } function foldable(item) { if (!item || item.nodeType != 1) return false; var node = item.firstChild; while (node) { if (node.nodeType == 1 && isBlock(node)) return true; node = node.nextSibling; } return false; } function fold(item) { if (item) { removeClass(item, "unfolded"); addClass(item, "folded"); } var node = item ? item.firstChild : null; while (node) { if (node.nodeType == 1 && isBlock(node)) // element { // note that getElementStyle won't work for Safari 1.3 node.display = getElementStyle(node, "display", "display"); node.style.display = "none"; node.style.visibility = "hidden"; } node = node.nextSibling; } item.visible = false; } function unfold(item) { if (item) { addClass(item, "unfolded"); removeClass(item, "folded"); } var node = item ? item.firstChild : null; while (node) { if (node.nodeType == 1 && isBlock(node)) // element { // with fallback for Safari, see above node.style.display = (node.display ? node.display : "block"); node.style.visibility = "visible"; } node = node.nextSibling; } item.visible = true; } function outlineClick(e) { var rightclick = false; var target; if (!e) var e = window.event; if (e.target) target = e.target; else if (e.srcElement) target = e.srcElement; // work around Safari bug if (target.nodeType == 3) target = target.parentNode; while (target && target.visible == undefined) target = target.parentNode; if (!target) return true; if (e.which) rightclick = (e.which == 3); else if (e.button) rightclick = (e.button == 2); if (!rightclick && target.visible != undefined) { if (target.foldable) { if (target.visible) fold(target); else unfold(target); } stopPropagation(e); e.cancel = true; e.returnValue = false; } return false; } function hoverOutline(e) { var target; if (!e) var e = window.event; if (e.target) target = e.target; else if (e.srcElement) target = e.srcElement; // work around Safari bug if (target.nodeType == 3) target = target.parentNode; while (target && target.visible == undefined) target = target.parentNode; if (target && target.foldable) target.style.cursor = "pointer"; return true; } function unhoverOutline(e) { var target; if (!e) var e = window.event; if (e.target) target = e.target; else if (e.srcElement) target = e.srcElement; // work around Safari bug if (target.nodeType == 3) target = target.parentNode; while (target && target.visible == undefined) target = target.parentNode; if (target) target.style.cursor = "default"; return true; } function stopPropagation(e) { if (window.event) { window.event.cancelBubble = true; //window.event.returnValue = false; } else if (e) { e.cancelBubble = true; e.stopPropagation(); //e.preventDefault(); } } /* can't rely on display since we set that to none to hide things */ function isBlock(elem) { var tag = elem.nodeName; return tag == "OL" || tag == "UL" || tag == "P" || tag == "LI" || tag == "TABLE" || tag == "PRE" || tag == "H1" || tag == "H2" || tag == "H3" || tag == "H4" || tag == "H5" || tag == "H6" || tag == "BLOCKQUOTE" || tag == "ADDRESS"; } function getElementStyle(elem, IEStyleProp, CSSStyleProp) { if (elem.currentStyle) { return elem.currentStyle[IEStyleProp]; } else if (window.getComputedStyle) { var compStyle = window.getComputedStyle(elem, ""); return compStyle.getPropertyValue(CSSStyleProp); } return ""; } // works with text/html and text/xhtml+xml with thanks to Simon Willison function createElement(element) { if (typeof document.createElementNS != 'undefined') { return document.createElementNS('http://www.w3.org/1999/xhtml', element); } if (typeof document.createElement != 'undefined') { return document.createElement(element); } return false; } // designed to work with both text/html and text/xhtml+xml function getElementsByTagName(name) { if (typeof document.getElementsByTagNameNS != 'undefined') { return document.getElementsByTagNameNS('http://www.w3.org/1999/xhtml', name); } if (typeof document.getElementsByTagName != 'undefined') { return document.getElementsByTagName(name); } return null; } /* // clean alternative to innerHTML method, but on IE6 // it doesn't work with named entities like   // which need to be replaced by numeric entities function insertText(element, text) { try { element.textContent = text; // DOM3 only } catch (e) { if (element.firstChild) { // remove current children while (element.firstChild) element.removeChild(element.firstChild); } element.appendChild(document.createTextNode(text)); } } // as above, but as method of all element nodes // doesn't work in IE6 which doesn't allow you to // add methods to the HTMLElement prototype if (HTMLElement != undefined) { HTMLElement.prototype.insertText = function(text) { var element = this; try { element.textContent = text; // DOM3 only } catch (e) { if (element.firstChild) { // remove current children while (element.firstChild) element.removeChild(element.firstChild); } element.appendChild(document.createTextNode(text)); } }; } */ function getSelectedText() { try { if (window.getSelection) return window.getSelection().toString(); if (document.getSelection) return document.getSelection().toString(); if (document.selection) return document.selection.createRange().text; } catch (e) { return ""; } return ""; } //]]>

XML Prague 2012

first

What's new in XQuery 3.0 and XPath 3.0?

Jonathan Robie <jonathan.robie@emc.com>
@jonathan_robie

Focus of this talk

head foot

Status: XQuery 3.0, XPath 3.0

head foot

Status: XQuery 3.0, XPath 3.0 (2)

head foot

Shared features in XPath 3.0 / XQuery 3.0

head foot

XQuery-only Features

head foot

FLWOR: group by clause

head foot

Input tuple stream

S101, $itemno = P78395)
    ($storeno = S102, $itemno = P94738)
    ($storeno = S101, $itemno = P41653)
    ($storeno = S102, $itemno = P70421)
    ]]>
    

group by clause


    

Output tuple stream

P78395, P41653))
    ($storeno =  S102, $itemno = (P94738, P70421))
    ]]>
    

Note: value of $storeno changed from current published spec.

Grouping sales by product

head foot

$sales is bound to a sequence of sales elements, e.g.:


   S101
   P78395
   125
]]>

$sales is bound to a sequence of products elements, e.g.:


   P78395
   25.00
   Men's Wear
]]>

Query:

]]>

Result:


]]>

Grouping sales by product and category

head foot

Query


    {for $s2 in $s1,
         $p in $products[itemno = $s2/itemno]
     let $category := $p/category,
         $revenue := $s2/qty * $p/price
     group by $category
     let $group-revenue := sum($revenue)
     where $group-revenue > 10000
     order by $group-revenue descending
     return 
    }
  ]]>

Result:


   


   
   
]]>

FLWOR: tumbling window and sliding window

head foot

FLWOR: tumbling window and sliding window - example

head foot

Query

Result

4 6 8 10 12

Use cases for tumbling and sliding windows

head foot

FLWOR: count clause

head foot

Input tuple stream

($name = "Bob", $age = 21)
($name = "Carol", $age = 19)
($name = "Ted", $age = 20)
($name = "Alice", $age = 22)

count clause

count $counter

Output tuple stream:

($name = "Bob", $age = 21, $counter = 1)
($name = "Carol", $age = 19, $counter = 2)
($name = "Ted", $age = 20, $counter = 3)
($name = "Alice", $age = 22, $counter = 4)

Example: Top N queries


      {$p/name, $p/sales}
   ]]>

FLWOR: allowing empty in for clause

head foot

try / catch expressions

head foot

Provides run-time error handling

try {
    $x cast as xs:integer
}
catch err:FORG0001 | err:XPTY0004 {
    0
}

Variables are implicitly bound in catch clause to identify error codes, descriptions, modules, line numbers, etc.

try {
    fn:error(fn:QName('http://www.w3.org/2005/xqt-errors', 'err:FOER0000'))
}
catch * {
    $err:code, $err:value, " module: ",
    $err:module, "(", $err:line-number, ",", $err:column-number, ")"
}

switch expressions

head foot

As in most languages you know ...

switch ($animal)
   case "Cow" return "Moo"
   case "Cat" return "Meow"
   case "Duck" return "Quack"
   default return "What's that odd noise?"

Computed namespace constructors

head foot

Allow namespace bindings to be created explicitly

Useful for namespaces in content

 {
  namespace xs {"http://www.w3.org/2001/XMLSchema"},
  attribute xsi:type {"xs:integer"},
  23
}]]>

Literal URIs in EQNames

head foot

Extends QNames so the entire name can be specified as a literal

BNF

URIQualifiedName 	   ::=    	URILiteral ":" NCName

Example

"http://www.w3.org/2005/xpath-functions/math":pi

Output declarations

head foot

Output declarations declare serialization parameters

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

declare option output:method   "xml";
declare option output:encoding "iso-8859-1";
declare option output:indent   "yes";

Can also put in a file

declare option output:parameter-document "file:///home/me/serialization-parameters.xml";

  
  
  
]]>

Files are the only way to do character maps


    
    
  
]]>