Exist: namespace constructor in computed constructor inconsistency

Created on 27 Jan 2017  路  12Comments  路  Source: eXist-db/exist

I stumbled on namespace constructors in Walmsley xQuery 2nd ed. p. 167-8 (the output of her example is in Example 10-9 Results).

xquery version "3.0";

declare namespace ok="http://place-on-interwebz.com/a-ok";
declare namespace doh="http://also-on-interwebz.com/problem";

element root {namespace {""} {"http://also-on-interwebz.com/problem"}, 
    namespace ok {"http://place-on-interwebz.com/a-ok"},
    for $n in 1 to 3
    return
        element stuff {$n}
}

output:

<root xmlns:ok="http://place-on-interwebz.com/a-ok">
    <stuff>1</stuff>
    <stuff>2</stuff>
    <stuff>3</stuff>
</root>

expected:

<root xmlns="http://also-on-interwebz.com/problem" 
    xmlns:ok="http://place-on-interwebz.com/a-ok">
    <stuff>1</stuff>
    <stuff>2</stuff>
    <stuff>3</stuff>
</root

the empty namespace prefix leads to the whole doh namespace uri part to be ommited.

Tested on eXist 2.2 via eXide and oxygen. Also tested with the xmldb:store active since there used to be a bug with how namespace appear in eXide's output vs. in stored documents.

bug

All 12 comments

So, I tested in 3.0 in the Java admin: the result is:

<root xmlns:ok="http://place-on-interwebz.com/a-ok">
    <stuff>1</stuff>
    <stuff>2</stuff>
    <stuff>3</stuff>
</root>

which is consistent. I tested the query also in Saxon (something one should always do when there is a doubt if the query engine in eXist-db is ok), resulting in:

Engine name: Saxon-PE XQuery 9.6.0.7
Severity: error
Description: XTDE0440: Cannot output a namespace node for the default namespace when the element is in no namespace
URL: http://www.w3.org/TR/xslt20/#err-XTDE0440

My conclusion is: yes you are right, eXist-db should give a different response, but it should yield into an error instead. eXide is not a factor in here. I did not check the book yet, but the example might be wrong?

tested with (a bit shorted whenever more readable and less error prone)

xquery version "3.0";

declare namespace ok="http://ok";
declare namespace doh="http://doh";

element root {namespace {""} {"http://doh"}, 
    namespace ok {"http://ok"},
    for $n in 1 to 3
    return
        element stuff {$n}
}

@dizzzz I ll leave it to someone with a better understanding of the xQuery specs to see if it should raise an error or have different results. I don't understand namespaces (1.1, or other) well enough. I just noticed that the current output could lead to problems, for documents with multiple namespaces. Everything in the output is in the doh namespace, which is missing its URI.

just checked running dizzz example in 3.1 stable via exide, now gives:

<root>
     <stuff>1</stuff>
     <stuff>2</stuff>
     <stuff>3</stuff>
</root>

somehow both namespaces are disappearing now., via oXygen:

<root xmlns:ok="http://ok">
    <stuff>1</stuff>
    <stuff>2</stuff>
    <stuff>3</stuff>
</root>

For me saxon's output is the reference output. SO there should be no output at all.... but an error should be raised.

Tested against Saxon 9.6.0.7 and BaseX 8.6.2:

1. eXist Bug

The provided query is invalid, i.e.

xquery version "3.0";

declare namespace ok="http://place-on-interwebz.com/a-ok";
declare namespace doh="http://also-on-interwebz.com/problem";

element root {namespace {""} {"http://also-on-interwebz.com/problem"}, 
    namespace ok {"http://place-on-interwebz.com/a-ok"},
    for $n in 1 to 3
    return
        element stuff {$n}
}

Saxon shows an error: XTDE0440: Cannot output a namespace node for the default namespace when the element is in no namespace.
Although I would note that XTDE0440 is from the XSLT spec.

BaseX shows an error: [XQDY0102] Duplicate namespace declaration: ''.

Instead in eXist we incorrectly get:

<root xmlns:ok="http://place-on-interwebz.com/a-ok">
    <stuff>1</stuff>
    <stuff>2</stuff>
    <stuff>3</stuff>
</root>

2. eXist OK

Modifying the query to what I suspect it was meant to be:

xquery version "3.0";

declare namespace ok="http://place-on-interwebz.com/a-ok";
declare namespace doh="http://also-on-interwebz.com/problem";

element ok:root {namespace {""} {"http://also-on-interwebz.com/problem"}, 
    namespace ok {"http://place-on-interwebz.com/a-ok"},
    for $n in 1 to 3
    return
        element stuff {$n}
}

Saxon and BaseX show the result:

<ok:root xmlns="http://also-on-interwebz.com/problem"
         xmlns:ok="http://place-on-interwebz.com/a-ok">
   <stuff xmlns="">1</stuff>
   <stuff xmlns="">2</stuff>
   <stuff xmlns="">3</stuff>
</ok:root>

eXist also shows the correct result:

<ok:root xmlns="http://also-on-interwebz.com/problem" xmlns:ok="http://place-on-interwebz.com/a-ok">
    <stuff xmlns="">1</stuff>
    <stuff xmlns="">2</stuff>
    <stuff xmlns="">3</stuff>
</ok:root>

A xqsuite test suite for this:

xquery version "3.0";

(:~
 : Tests for Computed Namespace Constructors
 :)
module namespace cnc = "http://exist-db.org/xquery/test/computed-namespace-constructors";

import module namespace test = "http://exist-db.org/xquery/xqsuite" at "resource:org/exist/xquery/lib/xqsuite/xqsuite.xql";

declare namespace ok="http://place-on-interwebz.com/a-ok";
declare namespace doh="http://also-on-interwebz.com/problem";


declare
    %test:assertError("XQDY0102")
function cnc:cannot-override-no-ns() {
    element root {namespace {""} {"http://also-on-interwebz.com/problem"},
        namespace ok {"http://place-on-interwebz.com/a-ok"},
        for $n in 1 to 3
        return
            element stuff {$n}
    }
};

declare
    %test:assertEquals(3)
function cnc:ns-default-constructor() {
    count(
        element ok:root {namespace {""} {"http://also-on-interwebz.com/problem"},
            namespace ok {"http://place-on-interwebz.com/a-ok"},
            for $n in 1 to 3
            return
                element stuff {$n}
        }/stuff
    )
};

I can't see an easy way to fix this though, as the computed namespace constructor has no reference to the enclosing computed element constructor.

I think this might require changes to our AST. @wolfgangmm @shabanovd any thoughts?

@adamretter thanks for looking into this, I'd prefer the baseX error message personally. Just to be sure, how did you check eXist output? Using eval in eXide 2.3.2 I still see the output from my previous post, ie <root> instead of <root xmlns:ok="http://place-on-interwebz.com/a-ok">. Should I raise a separate ticket in eXide for how results appear in the preview pane?

@duncdrum eval omitting not-in-use namespaces

Omitting not used namespaces is allowed if I remember correctly. Not sure where it is in which spec...

It's a feature, got it.

@duncdrum Regarding eXide, this issue might be relevant? https://github.com/wolfgangmm/eXide/issues/108

@duncdrum I used the Java Admin Client; I don't tend to use eXide.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

mathias-goebel picture mathias-goebel  路  4Comments

mathias-goebel picture mathias-goebel  路  4Comments

opax picture opax  路  3Comments

lguariento picture lguariento  路  5Comments

merenyics picture merenyics  路  3Comments