[xquery-talk] Generating xhtml from xml in no namespace

Michael Blakeley michael.blakeley at marklogic.com
Wed Dec 17 06:51:10 PST 2008


Andrew,

I don't like the '*:foo' shortcut either - it's nice for debugging, but 
it's a red flag when I'm doing code reviews.

The empty-namespace problem is much easier to work around than the 
earlier responses imply. The trick is to understand that every XPath 
expression evaluates in the current scope's default element namespace, 
but you can control the scope's default element namespace. 
http://marklogic.markmail.org/search/?q=namespace turns up some similar 
discussion threads.

I'll use MarkLogic Server 4.0 with cq as the query interface, and start 
with a standalone test case to show the problem:

xquery version "1.0";

declare variable $INPUT as document-node() := document {
<path>
   <to><node id="a1">hello andrew</node></to>
</path>,
<path>
   <to><node id="a2">hello world</node></to>
</path>
};

<html xmlns="http://www.w3.org/1999/xhtml">
   <body>
   <!-- there should be a span or two here -->
   {
      for $x in $INPUT/path/to/node
      order by $x
      return element span { text { $x } }
   }
   </body>
</html>

=>
<html xmlns="http://www.w3.org/1999/xhtml">
   <body>
     <!-- there should be a span or two here -->
   </body>
</html>

The result includes no spans, because $INPUT/path/to/node is looking for 
'path' etc in the xhtml namespace. Now let's try my preferred technique 
- a function call. This test will use a local function, but we could 
also use a library function. Either way, the function body starts with 
the same default element namespace as the XQuery module scope.

xquery version "1.0";

declare variable $INPUT as document-node() := document {
<path>
   <to><node id="a1">hello andrew</node></to>
</path>,
<path>
   <to><node id="a2">hello world</node></to>
</path>
};

declare function local:get-nodes()
  as element(node)+
{
   $INPUT/path/to/node
};

<html xmlns="http://www.w3.org/1999/xhtml">
   <body>
   <!-- there should be a span or two here -->
   {
      for $x in local:get-nodes()
      order by $x
      return element span { text { $x } }
   }
   </body>
</html>

=>
<html xmlns="http://www.w3.org/1999/xhtml">
   <body><!-- there should be a span or two here -->
   <span>hello andrew</span><span>hello world</span>
   </body>
</html>

That works, and it's my preferred solution. But here's another one, if 
you don't want to define a function:

...
<html xmlns="http://www.w3.org/1999/xhtml">
   <body>
   <!-- there should be a span or two here -->
   {
      <dummy xmlns="">{
        for $x in $INPUT/path/to/node
        order by $x
        return element span { text { $x } }
      }</dummy>/node()
   }
   </body>
</html>

=>
<html xmlns="http://www.w3.org/1999/xhtml">
   <body><!-- there should be a span or two here -->
   <span xmlns="">hello andrew</span><span xmlns="">hello world</span>
   </body>
</html>

I'm sure there are other approaches, but those are the two that came to 
mind. Hope that helps.

-- Mike

On 2008-12-17 06:08, Andrew Welch wrote:
> Yeah I saw that, thanks, but it's not really a reasonble solution...
> (in my humble opinion)
>
> I will go with xquery building the input to a transform which
> generates the xhtml, which is probably a nicer solution than using
> just xquery anyway.
>
> I was going to say that generating xhtml should be the #1 use case,
> but I guess using it in that way wasn't really expected?
>
>
>
> 2008/12/17 Jesper Tverskov<jesper.tverskov at gmail.com>:
>> I guess a wild card prefix would do as explained in my tutorial
>> "Creating XHTML with XQuery", http://www.xmlplease.com/xquery-xhtml.
>>
>>
>> for $x in collection(...)/*:path/*:to/*:node
>>
>>
>> Cheers,
>>
>> Jesper Tverskov
>> http://www.xmlplease.com
>> _______________________________________________
>> talk at x-query.com
>> http://x-query.com/mailman/listinfo/talk
>>
>
>
>



More information about the talk mailing list