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

Reply via email to