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> </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