In the previous sections we could seen several ways to reach the nodes. However, the XQuery language has the tools to create nodes dynamically (during run-time) as well. Its important to highlight the node identity again because the nodes created by the constructors always have a new identity.
While XQuery always flatten the sequences the nested application of node constructors is the only way to hierarchically structure values in XQuery. (It makes it possible to optionally replace an XSLT transformation with XQuery.) XQuery expressions may construct nodes with new identity of all seven node kinds known in XML. XQuery node constructors come in two flavors:
direct constructors: The syntax of direct constructors exactly matches the XML syntax: any well-formed XML fragment f also is a correct XQuery expression. Note: Text content and CDATA sections are both mapped into text nodes by the XQuery data model (“CDATA sections aren’t remembered.”)
computed constructors: The syntax of computed constructors are always introduced by a keyword and both its name and content could be computed dynamically of the new node.
The most important constructors:
document: creates a whole new XML document(document
{})
document {
<book year="1977">
<title>Harold and the Purple Crayon</title>
<author><last>Johnson</last><first>Crockett</first></author>
<publisher>HarperCollins Juvenile Books</publisher>
<price>14.95</price>
</book>
} Pay attention that existing documents always have the
invisible document root node. If we are working with XML
fragments this role is played by the most outer element,
like in a fragment with the
<x><y/></x>/* expression results
only a <y/> element.
element:
creates a new element in a direct way:
<x><![CDATA[foo & bar]]></x> ≡ <x>foo & bar</x> // a CDATA nem őrződik meg
The tag name of a direct constructor is constant, its content, however, may be computed by any XQuery expression enclosed in curly braces {···}. The dynamic construction is evaluated during execution!
<tag>3*3</tag> results the same what we see: <tag>3*3</tag>
in contrast, using a dynamic construct:
<tag>{3*3}</tag> the result: <tag>9</tag>However, it can be nested but only the outer dynamic construct is evaluated, inside the construct new evaluation could not occurred:
<tag>{<int>3*3</int>}</tag> result only a <int>3*3</int> part.
If we would like to continue this:
<tag>{
<int> {
let $x:=3
return $x*$x
}
</int>}
</tag>
Using our example from the surgery system:
for $p in /persons/person
return <newPerson>
{
let $info := $p/information/personalInformation
return
{
<name>{ data($info/name) }</name>,
<birthDate>{ data($info/birthDate) }</birthDate>
}
}
</newPerson>In the second dynamic construct we list all the new
nodes by separating with a coma - resulting a sequence.
Inside these nodes we do not have to create new
elements, so we have not used the element itself, rather
than we used the contained data. This value could be
requested from the node by the data
function.
creates a new element in a dynamic way:
element {expression_for_the_name}
{expression_for_the_value }
element { string-join(("foo","bar"),"-") } { 40+2 } => <foo-bar>42</foo-bar>This construction makes it possible to replace XSLT with XQuery in some situations. Take the example, replacing word in a file using a dictionary:
// the dictionary
<entry word="address">
<variant lang="de">Adresse</variant>
<variant lang="it">indirizzo</variant>
</entry>
// relacng the element (+ attributes):
element
{ $dict/entry[@word=name($e)]/variant[lang="it"] }
{ $e/@*, $e/node() }attribute:
direct mode:
<x a="{(4,2)}"/> => <x a="4 2"/>dynamic way:
attribute {expression_for_the_name}
{expression_for_the_value
}
element book {
attribute year { 1977 },
element author {
element first { "Crockett" },
element last { "Johnson" }
},
element publisher {"HarperCollins Juvenile Books"},
element price { 14.95 }
}text
direct mode: characters in the element content with CDATA section. Content sequence e is atomized to yield a sequence of type anyAtomicType*. The atomic values are converted to type string and then concatenated with an intervening " ".
dynamic:
text {expression}
if (empty(e))
then ()
else text { string-join(for $i in data(e)
return string($i)," ") }
The XQuery element constructor is the most flexible because the content sequence is not restricted and may have type item*. The construction consists the following steps:
Consecutive literal characters yield a single text node containing these characters.
Expression enclosed in {···} are evaluated.
Adjacent atomic values are cast to type string and collected in a single text node with intervening " ".
A node is copied into the content together with its content. All copied nodes receive a new identity.
Then, adjacent text nodes are merged by concatenating their content. Text nodes with content "" are dropped.
// Evaluate the expression below:
count(
<x>Fortytwo{40 + 2}{ "pi",3.1415,<y><z/></y>,("","!")[1] }</x>/node()
)We need to take care on one thing during the construction of the content: well-formed element content is needed. (I.e.: no two attributes of the same element may share a name and attribute nodes precede any other element content.) Finally, construction establishes document order!