With templating in mind, what's the best way to structure a web-app
internally? I've taken a look at cq and versi. I'll illustrate briefly
what I'm leaning towards, and would appreciate any comments/suggestions.
The ubiquitous case involves some template of a header and footer, and
poking real page content in the main content area(s) (generally divs).
So here's a (simplified) template, which resides in an xquery module
file. The t:html function takes a $content item, an $options element
with various options, such as page title.
xquery version "1.0"
module "http://my.template"
declare namespace t = "http://my.template"
declare namespace xhtml = "http://www.w3.org/1999/xhtml"
declare namespace void = ""
default function namespace = "http://www.w3.org/2003/05/xpath-functions"
define function t:html($content as item()*, $options as element(options))
as element(xhtml:html)
{
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{ $options/void:title/text() }</title>
</head>
<body>
<div id="page">{ $content }</div>
</body>
</html>
}
Questions:
1. In every xquery module file, since I almost always have
xpath-functions (fn:) as the default function namespace, I also have to
duplicate the module namespace in a its own namespace declaration (in
this case, the "t" namespace). There's no way to avoid this boilerplate
line of code?
2. Is it common to declare a variable for the no-namespace (in this
case, the "void" namespace), to use in places where you're in a default
namespace context and don't want to be? (See the line poking the page
title into the <title> element)
3. Does it make sense to pass $content as an item()? Is it too
restrictive to specify $content as element(xhtml:div)*, or even $content
as element(div)* ? $content will almost certainly be some xhtml
structure, rather than a one-line string.
4. Any comments on the t:html function specifying it's return type as
element(xhtml:html)? This could also be element(html), or even just
element().
5. The xmlns="http://www.w3.org/1999/xhtml" attribute in the html
element -- I know it puts itself and all children into a default
namespace (in this case, the xhtml namespace), but what does this
actually do for me? My guess is...if I remove that, then the return
type of the function should become element(html) (or element()), and the
fact that IE6 renders everything properly in that situation, and FF
displays the DOM tree, means this has something to do with
xdmp:set-response-content-type being application/xhtml+xml vs text/html.
I didn't show this above, but I have code similar to what cq does in
terms of checking if xdmp:get-request-header('accept') contains
application/xhtml+xml, and if so, uses xdmp:set-response-content-type to
set the content-type to application/xhtml+xml, rather than text/html.
6. Assuming I want my content-type to be application/xhtml+xml (where
possible), xmlns="http://www.w3.org/1999/xhtml" as the attribute to the
html element, and function returning element(xhtml:html), what does this
mean for $content being passed in? If I pass in <div><p>hi</p></div>,
it renders as <div xmlns=""><p>hi</p></div>. Is that fine, or could
that div and it's children, which are now in the no-namespace rather
than the xhtml namespace, render in different/unexpected ways? If I
pass in <div xmlns="http://www.w3.org/1999/xhtml"><p>hi</p></div> from
all my view-level files, which will get tedious to say the least, it
renders nicely as <div><p>hi</p></div>. Which method do I want here?
Thanks in advance to any responses, and I apologies for the barrage of
questions. As a new xquery developer I'm grateful for a responsive
mailing list.
Cheers,
Eric
Michael Blakeley wrote:
Yes, it's namespaces - good hunch.
In your html element, xmlns="..." is a default element namespace
declaration. It applies to both XML and XPath expressions within that
scope, so $options/title in the enclosed expression is is identical to
$options/xhtml:title, which matches nothing.
A simple fix is to move the XPath expression outside the scope of the
default element namespace declaration:
define function display:html($options as element(options))
as element(xhtml:html)
{
let $title as xs:string := $options/title
return <html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{ $title }</title>
</head>
...
</html>
}
As a debugging technique, you could also have tried $options/*:title -
the asterisk matches any namespace. However, this technique is perilous:
you might match a:title when you wanted b:title. If you do want both
kinds of title, it's less error-prone to write 'a:title|b:title'. As a
code review practice, I recommend looking for and rewriting any uses of
'*:' that sneak into your XQuery.
-- Mike
Eric Palmitesta wrote:
Secondly, I followed your example, approximately. I have a function
which returns an element(xhtml:html), which xhtml is declared as the
namespace "http://www.w3.org/1999/xhtml". The root node is <html
xmlns="http://www.w3.org/1999/xhtml">. I pass into this function an
<options> element, containing for example a <title>.
define function display:html($options as element(options))
as element(xhtml:html)
{
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>{ $options/title/text() }</title>
</head>
...
</html>
}
Probably a namespace problem than anything else, but the title text
isn't rendered, as if the $options variable wasn't even there.
Suggestions?
--
Thirdly, thanks for all the great responses, everyone, you've given me
much to read (on the mailing list and external links). Much appreciated!
Eric
_______________________________________________
General mailing list
[email protected]
http://xqzone.com/mailman/listinfo/general