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

Michael Blakeley wrote:
Eric,

I think it's important to distinguish between server behavior and browser behavior. While we can use XQuery to generate valid XHTML on the server, the browser may decide to interpret it as quirky HTML tag-soup. This is commonly known as "quirks mode" (vs "standards compliance mode" - apologies if you already know all this), and Mozilla-family browsers will tell you which mode was used for the current page (on Firefox 3, Tools > Page Info).

In my experience, it's best to avoid quirks mode by persuading the browser to render in standards-compliance mode: that is, tell the browser to expect XHTML. When I combine the XHTML doctype with the xhtml namespace, I find that I don't need any special tricks with <textarea/> elements. Here's an example:

xquery version "1.0";

declare variable $ACCEPT-XML as xs:boolean :=
  (: Opera says that it accepts xhtml+xml, but does not. :)
  contains(xdmp:get-request-header('accept'), 'application/xhtml+xml')
    and not(contains(xdmp:get-request-header('user-agent'), 'Opera'))
;

xdmp:set-response-content-type( concat(
  if ($ACCEPT-XML) then "application/xhtml+xml" else "text/html",
  "; charset=utf-8") ),
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "DTD/xhtml1-transitional.dtd">',
<html xmlns="http://www.w3.org/1999/xhtml";>
  <head>
    <title>test</title>
  </head>
  <body>
    <textarea></textarea>
  </body>
</html>

Some of the above code was lifted from cq/lib-controller.xqy - cq is itself a moderately complex XQuery + XHTML + JavaScript application, and while its code isn't always as clean as I might like, it hopefully provides some useful examples. All of the cq source code is open under the Apache license.

-- Mike

Eric Palmitesta wrote:
Aaron and I discussed this briefly at the training seminar, but I'd like to get a sense of what other developers are doing to get around the quirks of generating xhtml with xquery (rather than a java servlet/jsp based website which pulls records from MarkLogic via XDBC/XCC.

One such quirk: Childless elements with no internal nodes and an explicit closing tag are automatically folded into elements with no closing tag. <div></div>, which is valid xhtml, will become <div /> after being processed by MarkLogic (breaks visual representation). Some better examples are <script ...></script> and <textarea></textarea>, which are expected to contain no internal nodes in xhtml.

I've taken to writing things like

<script ... >{" "}</script>

or

<textarea>&nbsp;</textarea>

which successfully preserves the explicit closing tag, keeping xhtml happy. Is there a more elegant way to do this?

Are there other banana-peels I should watch out for when generating xhtml with xquery? Is creating an entire website by generating xhtml with xquery generally frowned upon, or accepted? Admittedly, it seems less flexible than a <web language>-based site, however the xdmp namespace seems to provide sufficient functionality, and transforming xml data into xhtml is incredibly easy with xquery.

Cheers,

Eric


PS
My vocabulary might be incorrect regarding words like 'tag' and 'node', please correct me if necessary.

PPS
I can see the archives at http://xqzone.marklogic.com/pipermail/general/ but are they searchable? I have a feeling newcomers such as myself will be prone to asking questions which have already been discussed at length.
_______________________________________________
General mailing list
[email protected]
http://xqzone.com/mailman/listinfo/general
_______________________________________________
General mailing list
[email protected]
http://xqzone.com/mailman/listinfo/general
_______________________________________________
General mailing list
[email protected]
http://xqzone.com/mailman/listinfo/general

_______________________________________________
General mailing list
[email protected]
http://xqzone.com/mailman/listinfo/general

Reply via email to