XQuery lives to make XML.
This XQuery:
<created date="today">just for
<reader>you</reader>
</created>
constructs the element <created>, just like that.
(try it: put that XQuery into CQ that you set up in the tutotial)
<created> is a real live element, one of the seven types of nodes in the XQuery data model.
You can store it, access it, and, much more fun, query it:
let $node := <created date="today">just for <reader>you</reader></created>
return
$node[@date eq "today"]/reader
This uses a basic XPath predicate to test the value of the @date attributte and returns, (ta-da) the reader node:
<reader>you</reader>
Lets make some more XML:
let $node := <created date="today">just for <reader>you</reader></created>
return
element read {
"by ",
$node/reader
}
Whao! What was that?
Meet the XQuery computed contstructor, where XQuery gets it hardhat on.
Using the values in our element <created> (which was a direct constructor), we dynamically created a new element <read>:
<read>
by <reader>you</reader>
</read>
The computed constructors are expressions, not functions. So 'element' is a keyword in XQuery (just like 'if' or 'for'). This is followed by the name of the element and an expression to create the contents of the element.
Alert: XQuery *can* be very strongly typed (in this case element name must be of type xs:QName). This can be complicated. But, thankfully, XQuery has a flexible type checking mechanism that allows you to enforce type when you need it (like when you need to return an xs:QName for a dynamic element constructor), but also not worry about it most of the time.
There are constructors to create any bit of XML you like:
let $node := <created date="today">just for <reader>you</reader></created>
return
element {xs:QName(data($node/@date))}
{
comment {$node//text()},
<node>{$node}</node>, <action>read {attribute by {$node/reader/text()}}</action>
}
Creates this:
<today>
<!--just for you-->
<node><created date="today">just for <reader>you</reader></created></node>
<action by="you">read </action>
</today>
There are many ways that this can be used . . . but I found it pretty useful when I had to dynamically create some javascrpt in XHTML using XQuery.
As you might guess, the XML and XQuery data model doesn't have any support for javascript. This was actually true of HTML as well (back in the stone ages of the web) and, back then, I learned how to hide javascript inside an HTML comment (which in turn has to be in a javascript comment) so that IE 3.0 wouldn't show it.
It works XQuery too:
let $node := <created date="today">just for <reader>you</reader></created>
return
<html><head>
<title>The Javascript Trick</title>
</head>
<body>
<script type="text/javascript">
//
{comment {fn:concat('
document.write("<p>Thank ', $node/reader, ', ', fn:local-name($node/reader), ', ', ' for reading my blog ', data($node/@date), '!</p>");
// ')}
}
</script>
</body>
</html>
which renders:
Thank you, reader, for reading my blog today!
Indeed!
P.S. you have to include the newlines in the javascript trick - javascript is line sensitive!