Exist: Adding namespace nodes leads to illegal XML

Created on 2 Oct 2018  ยท  10Comments  ยท  Source: eXist-db/exist

eXist-db 4.4.0

When you run the following code you get illegal XML

xquery version "3.0";

let $xml    :=
    <MCCI_IN200101 xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:hl7nl="urn:hl7-nl:v3">
โ€‚โ€‚โ€‚โ€‚โ€‚โ€‚โ€‚โ€‚<effectiveTime xsi:type="hl7nl:PIVL_TS"/>
โ€‚โ€‚โ€‚โ€‚</MCCI_IN200101>

return
    for $in in $xml/*
    return
        element {name($in)} {
            $in/@*,
            for $nsp in in-scope-prefixes($in)
            return
                namespace {$nsp} {namespace-uri-for-prefix($nsp, $in)}
            ,
            $in/node()
        }

Actual output:
<effectiveTime xmlns="urn:hl7-org:v3" xmlns:hl7nl="urn:hl7-nl:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="" xsi:type="hl7nl:PIVL_TS"/>

Expected output:
<effectiveTime xmlns="urn:hl7-org:v3" xmlns:hl7nl="urn:hl7-nl:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="hl7nl:PIVL_TS"/>

Related to https://github.com/eXist-db/exist/issues/2182

bug regression

All 10 comments

I think this may be a variant or duplicate of https://github.com/eXist-db/exist/issues/1237.

@joewiz i agree, exist should not output illegal xml here.

actually when executing the code from the OP, Saxon returns an error for me:
9.8.0.12 EE (via oXygen)

Cannot output a namespace node for the default namespace when the element is in no namespace
--

If I modify the code to take the empty namespace of the root element of the return statement element {name($in)} into account, i get the desired result:

xquery version "3.0";

let $xml    :=
    <MCCI_IN200101 xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:hl7nl="urn:hl7-nl:v3">
โ€‚โ€‚โ€‚โ€‚โ€‚โ€‚โ€‚โ€‚<effectiveTime xsi:type="hl7nl:PIVL_TS"/>
โ€‚โ€‚โ€‚โ€‚</MCCI_IN200101>

return
    for $in in $xml/*
    return
        element {fn:QName('urn:hl7-org:v3', name($in))} {
            $in/@*,
            for $nsp in in-scope-prefixes($in)
            return
                namespace {$nsp} {namespace-uri-for-prefix($nsp, $in)}
            ,
            $in/node()
        }

Saxon returns the expected result

<effectiveTime xmlns:hl7nl="urn:hl7-nl:v3"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="urn:hl7-org:v3"
 xsi:type="hl7nl:PIVL_TS"/>

exist however

err:XQDY0074  prefix cannot be cast to xs:NCName

So namespace are fun, right?

  • bug 1: exist should not output illegal xml but throw an error when facing a bad query.
  • bug 2: my adjusted query throws an error in exist, which it should not. It should return the desired output in line with Saxon

a somewhat simplified version of the OPs query

xquery version "3.0";

let $xml    :=
    <no_pre xmlns="foo" xmlns:xsi="http://XMLSchema-instance" xmlns:pre1="bar">
โ€‚โ€‚โ€‚โ€‚โ€‚โ€‚โ€‚โ€‚<effectiveTime xsi:type="pre1:foobar"/>
โ€‚โ€‚โ€‚โ€‚</no_pre>

return
    for $in in $xml/*
    return
        element {fn:QName('foo', name($in))} {
            $in/@*,
            for $nsp in in-scope-prefixes($in)
            return
                namespace {$nsp} {namespace-uri-for-prefix($nsp, $in)}
            ,
            $in/node()
        }

so looking at our own testsuite (!) it seems we are well aware of the NCName behaviour:

this seems to have somewhat dropped under the radar. While there are workarounds, any insights into how to fix this @eXist-db/core ?

see #2140

@duncdrum Yes, I think one of my changes for #2140 should fix that.

So Bug 1 has been fixed, that is a badly formatted query now results in the appropriate error instead of not well-formed xml. ๐ŸŽ‰
Bug2 however is still present, here is a proper test.

xquery version "3.1";

module namespace t="http://exist-db.org/xquery/test";

declare namespace test="http://exist-db.org/xquery/xqsuite";
(:~ @see https://github.com/eXist-db/exist/issues/2183 
 :)
declare variable $t:xml := document {
<MCCI_IN200101 xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:hl7nl="urn:hl7-nl:v3">
   <effectiveTime xsi:type="hl7nl:PIVL_TS"/>
</MCCI_IN200101>
};

(:~ function throws an err:XQDY0074 it should not switch below to verify :)
declare
    %test:assertTrue
(:    %test:expectError('err:XQDY0074'):)
function t:NCName_namespace() {
    let $test := for $in in $t:xml/*
        return
            element {fn:QName('urn:hl7-org:v3', name($in))} {
                $in/@*,
                for $nsp in in-scope-prefixes($in)
                return
                    namespace {$nsp} {namespace-uri-for-prefix($nsp, $in)}
                ,
                $in/node()
            }
    let $proof := <effectiveTime xmlns:hl7nl="urn:hl7-nl:v3"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="urn:hl7-org:v3"
 xsi:type="hl7nl:PIVL_TS"/>

    return
        deep-equal($proof, $test)
};

tested in 5.3.0-SNAPSHOT (Exist-build: 20200608161727)

hold on a second getting conflicting results from XQsuite and simply executing the query.
ok executing the following query in exide results in err:XQDY0074 prefix cannot be cast to xs:NCName

xquery version "3.1";

declare variable $xml :=
<MCCI_IN200101 xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:hl7nl="urn:hl7-nl:v3">
   <effectiveTime xsi:type="hl7nl:PIVL_TS"/>
</MCCI_IN200101>
;

declare function local:test() {
    for $in in $xml/*
        return
            element {fn:QName('urn:hl7-org:v3', name($in))} {
                $in/@*,
                for $nsp in in-scope-prefixes($in)
                return
                    namespace {$nsp} {namespace-uri-for-prefix($nsp, $in)}
                ,
                $in/node()
            }
};

local:test()

the same contents as XQsuite test, however, now seem to return the desired result ?!? aka the following passes.

xquery version "3.1";

module namespace t="http://exist-db.org/xquery/test";
declare namespace test="http://exist-db.org/xquery/xqsuite";
(:~ @see https://github.com/eXist-db/exist/issues/2183 
 :)

declare variable $t:xml :=
<MCCI_IN200101 xmlns="urn:hl7-org:v3" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:hl7nl="urn:hl7-nl:v3">
   <effectiveTime xsi:type="hl7nl:PIVL_TS"/>
</MCCI_IN200101>
;

(:~ function throws an err:XQDY0074 it should not switch below to verify :)
declare
    %test:assertEquals('<effectiveTime xmlns:hl7nl="urn:hl7-nl:v3"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="urn:hl7-org:v3"
 xsi:type="hl7nl:PIVL_TS"/>')
(:    %test:assertError('err:XQDY0074'):)
function t:NCName_namespace() {
    for $in in $t:xml/*
        return
            element {fn:QName('urn:hl7-org:v3', name($in))} {
                $in/@*,
                for $nsp in in-scope-prefixes($in)
                return
                    namespace {$nsp} {namespace-uri-for-prefix($nsp, $in)}
                ,
                $in/node()
            }
};

frankly i don't see how that could ever be the case, the contents are simply copy-pasted.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

adamretter picture adamretter  ยท  4Comments

joewiz picture joewiz  ยท  3Comments

lguariento picture lguariento  ยท  5Comments

merenyics picture merenyics  ยท  3Comments

dizzzz picture dizzzz  ยท  5Comments