What is the element constructor in xQuery? - xquery

I'm reading a book about xQuery and it is full of expression like element constructor... and my question is:
What is the element constructor and is "{<expression>}" an element constructor?

An element constructor creates an element. There are several ways that you can do that in XQuery.
The curly braces {} mark the beginning and end of an enclosed expression in XQuery. Since you can use literal XML and computed expressions, the curly braces denote when you are leaving the static context and entering the dynamic constructs. Similar to how you would use <%# page ... %> for JSP directives.
With a direct element constructor, you use XML syntax to create a static XML structure.
For instance:
<book isbn="isbn-0060229357">
<title>Harold and the Purple Crayon</title>
</book>
With a computed element constructor, an element node and content and can generate dynamic XML structure from expressions for the element name and it's content.
For example:
element book {
attribute { "isbn" } { "isbn-0060229357" },
<title>Harold and the Purple Crayon</title>
}
You can also use an expression to compute the element name:
element { fn:concat("bo", "ok") } {
attribute { "isbn" } { "isbn-0060229357" },
<title>Harold and the Purple Crayon</title>
}

I'm surprised that a book should use the term without explaining it, but your next port of call should be the W3C XQuery specification,
https://www.w3.org/TR/xquery-31/#id-constructors
Unlike many language specifications, the XQuery specs are designed to be quite readable by ordinary users, provided you can follow BNF, and they have lots of examples.

Related

Reference to root element as key in JSON Path Expression

I have a JSON like this
{
"a" : 1,
"key_to_find" : "value_of_key",
"nested" : {
"value_of_key" : "real_value",
"b" : 2
}
}
I want to create a JSON Path expression to get "real_value", but I don't now the key "value_of_key" so I need to dynamically reference it.
I tried something like:
$.nested['$.key_to_find']
but it doesn't work.
How can I reference to root element value as key to get children values? Is that possible?
I need to use it inside AWS Step Functions, so no programming languages/libraries can be used.
References like this aren't part of JSON Path, though I think since you're using them inside AWS, you'll need to see exactly what they support. It varies. Widely.
We (the team working on the coming specification) have looked at the idea of a key() or index() function, however. You may find this discussion enlightening as well.

Polymer: What is the data-binding syntax attribute-name\$ for?

I have come across some syntax I don't understand. The docs for data binding in Polymer explain 2 different syntaxes for data bindings:
One for binding to properties:
prop-name=...
And one for binding to attributes (e.g. href, src, style etc.):
attr-name$=...
Trying to learn from source code of existing components I have come accross the construct name\$=... and I haven't found any documentation on what that is, so far.
In the source for <paper-input> there is e.g. the following data binding for the hidden attribute on a label element:
<label hidden\$="[[!label]]" ... >[[label]]</label>
hidden is not even on the list of properties, that require attribute binding (although that list may be incomplete). So I'm feeling really stuck (and confused) here.
Why is this hidden\$=... (i.e. with a backslash) and not just hidden$=..." (without the backslash) or hidden=... (without backslash and without dollar sign)? What does this syntax do? What is it used for?
A data binding appears in the local DOM template as an HTML attribute:
property-name=annotation-or-compound-binding
attribute-name$=annotation-or-compound-binding
The left-hand side of the binding identifies the target property or attribute.
To bind to a property, use the property name in attribute form (dash-case not camelCase), as described in Property name to attribute name mapping:
<my-element my-property="{{hostProperty}}">
This example binds to the target property, myProperty on .
To bind to an attribute instead, use the attribute name followed by $:
<a href$="{{hostProperty}}">
This example binds to the anchor element's href attribute.
https://www.polymer-project.org/3.0/docs/devguide/data-binding

XQuery: How to set default namespace with a computed namespace constructor?

Setting a default namespace with a direct element constructor is straightforward. Ex:
<map xmlns="http://www.w3.org/2013/XSL/json"/>
The above direct constructor outputs the exact same element, as expected. However, if I try to do the same with computed element and namespace constructors, I'm out of luck:
element {"map"} {
namespace {""} { "http://www.w3.org/2013/XSL/json" }
}
The above throws a Duplicate namespace declaration: '' error in BaseX 8.2; and a XTDE0440: Cannot output a namespace node for the default namespace when the element is in no namespace in Saxon-HE 9.6.
There's no problem if I pass a prefix. The following works well:
element {"map"} {
namespace { "e" } {"http://www.w3.org/2013/XSL/json"}
}
In the above case, neither BaseX nor Saxon complain. But I want to set the namespace as the default namespace.
Regarding computed namespace constructors, the XQuery 3.0 spec says:
If the constructor specifies a PrefixExpr, the prefix expression is evaluated as follows:
b. If the result is the empty sequence or a zero-length xs:string or xs:untypedAtomic value, the new namespace node has no name (such a namespace node represents a binding for the default namespace).
The spec also provides a similar example of a "computed namespace constructor with an empty prefix":
namespace { "" } {"http://a.example.com" }
Why then, the error messages? Apparently, the computed namespace constructor tries to re-declare a namespace already declared by the computed element constructor. On the other hand, the direct constructor would be directly initializing the element's namespace to my choice. But this is just my guess. My only certainty is my puzzlement.
In any case, is there a way to obtain with computed constructors the same result achievable with the direct constructor?
The basic reason is that the name of an element (that is, the prefix, local, and uri parts of the name) are determined by the element constructor itself, and not by the dynamic content that is added to the element.
When you do this:
element {"map"} {
namespace {""} { "http://www.w3.org/2013/XSL/json" }
}
You are creating an element with no prefix and no namespace, and then you are giving it a namespace node that binds the default namespace to something other than "no namespace"; you can't have it both ways. Adding a namespace dynamically to the content of an element will never change the element name.
I haven't tested this in saxon or basex, but using XQuery3 in Marklogic, this works:
element {fn:QName("http://www.w3.org/2013/XSL/json", "map")} { }
However, that alone probably won't actually do what you want.
In XQuery, computed constructors do not inherit default namespaces from parent elements; the first part is always the (fully qualified) QName of the element. You can use a string there, but it's being coerced into a QName - if that string has no prefix then you're explicitly asking for an element with no namespace (unless you've declared a default element namespace, in which case, you're asking for that). This means that even if you set the default namespace on an element, any children for which you don't specify a default namespace in the constructor will explicitly set it back to "".
By far the simplest way to work with computed constructors is to declare your namespaces at the top of the file, and then use prefixes on every element name. This does lead to XML with prefixes on every element though. Personally, I like how obviously unambiguous that is, but many people find it overly verbose, especially in XML that uses only one namespace.
You can also use the construct I used above for every element, which will do more or less the same thing, but without using prefixes. If you do this, while you have to specify the namespace on every element where it's constructed in your code, the resulting XML should only specify it on the top-level element, with child elements inheriting it like you'd expect (although it's possible this will depend on your XQuery processor.)
Alternatively, you can declare the default element namespace and then only specify a namespace for elements that differ from that. Personally, I find this confusing and prone to hard to spot errors, though.
I tried to add a comment but it wouldn't let me put in newlines.
As Will Goring mentioned in his answer, children elements do not inherit the default namespace from the parent. One way to make this easier is to declare the namespace and use that in the children elements.
declare namespace json = "http://www.w3.org/2013/XSL/json";
element {fn:QName("http://www.w3.org/2013/XSL/json", "map")} {
element json:child { }
}
becomes
<map xmlns="http://www.w3.org/2013/XSL/json"><child/></map>
where child has the same default namespace.
It's equivalent to:
element {fn:QName("http://www.w3.org/2013/XSL/json", "map")} {
element {fn:QName("http://www.w3.org/2013/XSL/json", "child")} { }
}

Indentity Transform with Namespaces

There is a well known Identity Transform sample code in the XQuery wikibook
But it works well only with no namespace documents, or explicitly declaring the namespaces with the same prefixes used in the document about to be processed.
If you don't declare the namespaces (with the same prefixes), you get an error:
Cannot compile xquery: err:XPST0081 No namespace defined for prefix
xsd [at line 15, column 12]
is there a way to write an Identity Transform in XQuery, that can automatically handle the namespaces and prefixes, avoiding the explicit declaration of namespaces?
EDIT:
This is the code from the Wikibook:
(: return a deep copy of the element and all sub elements :)
declare function local:copy($element as element()) as element() {
element {node-name($element)}
{$element/#*,
for $child in $element/node()
return
if ($child instance of element())
then local:copy($child)
else $child
}
};
In my case, I don't know the namespaces or prefixes in the document to be processed, so the element { } { } construct fails if the namespace and prefix are not declared in the XQuery.
To reproduce it, just copy/paste and run it with a document that uses prefixed namespaces.
I think the answer is no. If you want to process namespaced elements, then those namespaces need to be declared.
Based on the error message, all you need to do is declare the xsd namespace at the top of your XQuery document.
Declare namespace xsd="http://www.w3.org/2001/XMLSchema";
If this doesn't do it, then posting your XQuery would greatly help us understand what the issue is.

Dynamic CSS class names in GWT

I am in the process of porting a simple CSS grid system to GWT. My CSS file currently has classes like .size1, .size2 etc., and I have a CSS resource that looks like -
interface MyResource extends CSSResource {
#ClassName("size1")
String size1();
#ClassName("size2")
String size2();
// And so on
}
However what I really want, is to have a single function like the following -
String size(int size);
which will generate the appropriate class when passed the size as an integer at runtime. This is needed as I perform some calculations to determine the actual space available/needed for a widget in javascript and then attach the appropriate class name.
Is this something that is even possible with GWT?
Edit: To clarify, I can easily write such a method myself like so -
String size(int size) {
switch(size) {
case 1: return size1();
case 2: return size2();
... and so on
}
}
However MyResource is an interface and its implementation is generated at runtime by GWT. This means I cannot add my size method to the MyResource type. So I guess I am asking for a way to add custom methods to the MyResource class.
I think you should not try to solve this via css files, but if you want to have dynamic values in your style you should set those values in code via myWidget.getElement().getStyle().setSomeCssMethod(). Or in this case you seem to want to set size, as in height and width. For most widgets those values can be set directly. Unless I'm missing something, why do you want to use css classes and not set it directly in code?
You can't pass method names to the CSSResource.
Remember that CSSResource's purpose is to minify and obfuscate the CSS class names.
However, just because CSS Resource can do this, doesn't mean you have to use it for all you code.
For example you already know that the CSS Resource methods return a string, so just create your own method that returns a string (your dynamic class names) and to load your CSS use the #CssResource.NotStrict annotation when adding it to your resource.

Resources