Hi all,
I just come across an issue, and I am not sure if I am too stupid to see the mistake, or it is a bug in BaseX.
I need to create an XML document from data in BaseX 11.5 inside basexgui. The data in the database does not use any namespaces. The document I am creating must have a default namespace set. Here is a stripped down example of my XQuery:
for $w in /json/workouts/_/header[uuid='123'] return <gpx xmlns="http://www.topografix.com/GPX/1/1" > <title>{$w/title/text()}</title> </gpx>
Strangely all XPaths inside and outside the gpx-element will not match anything as long as I have the default namespace on the gpx-element defined. It works if I drop the xmlns attribute or I define the namespace explicitly, like:
for $w in /json/workouts/_/header[uuid='123'] return <g:gpx xmlns:g="http://www.topografix.com/GPX/1/1" > <g:title>{$w/title/text()}</g:title> </g:gpx>
Even though this should be semantically equal to the output of the above, the third party app that I import this to does not recognize it as such.
This is puzzling me mainly because I do not see, why the namespace I define for the *output* xml should have an impact on the queries that are directed to my database. As a workaround I will probably use a regex to remove the namespace, but that's obviously pretty awkward.
Any ideas?
Cheers Jörn
Hello Jörn,
I need to create an XML document from data in BaseX 11.5 inside basexgui. The data in the database does not use any namespaces. The document I am creating must have a default namespace set. Here is a stripped down example of my XQuery: for $w in /json/workouts/_/header[uuid='123'] return
<gpx xmlns="http://www.topografix.com/GPX/1/1" > <title>{$w/title/text()}</title> </gpx> Strangely all XPaths inside and outside the gpx-element will not match anything as long as I have the default namespace on the gpx-element defined. It works if I drop the xmlns attribute or I define the namespace explicitly, like: for $w in /json/workouts/_/header[uuid='123'] return <g:gpx xmlns:g="http://www.topografix.com/GPX/1/1" > <g:title>{$w/title/text()}</g:title> </g:gpx>
I think I made a standalone (no database) example that illustrates your issue:
let $doc := document { <json> <workouts> <_> <header> <uuid>123</uuid> <title>title 1</title> </header> </_> <_> <header> <uuid>123</uuid> <title>title 2</title> </header> </_> </workouts> </json> } let $gpx1 := for $w in $doc/json/workouts/_/header[uuid='123'] let $title := $w/title/text() return <gpx xmlns="http://www.topografix.com/GPX/1/1" > <title>{$w/title/text()}</title> <titlex>{$w/*:title/text()}</titlex> <titley>{$title}</titley> </gpx> let $gpx2 := for $w in $doc/json/workouts/_/header[uuid='123'] return <g:gpx xmlns:g="http://www.topografix.com/GPX/1/1" > <g:title>{$w/title/text()}</g:title> </g:gpx> return ( $gpx1 , $gpx2 )
When I run this in the BaseX GUI, I get
<gpx xmlns="http://www.topografix.com/GPX/1/1"><title/><titlex>title 1</titlex><titley>title 1</titley></gpx> <gpx xmlns="http://www.topografix.com/GPX/1/1"><title/><titlex>title 2</titlex><titley>title 2</titley></gpx> <g:gpx xmlns:g="http://www.topografix.com/GPX/1/1%22%3E<g:title>title 1</g:title></g:gpx> <g:gpx xmlns:g="http://www.topografix.com/GPX/1/1%22%3E<g:title>title 2</g:title></g:gpx>
The default namespace on <gpx> becomes the default namespace in the XPath expression. I am not sure if this is correct, and I have not looked this up in the specification.
Maybe someone who is more knowledgeable can tell if this behaviour is correct. For now, I suggest you use the additional $title variable.
Best regards, Nico Verwer
On 10/01/2025 09:12, Nico Verwer (Rakensi) wrote:
The default namespace on <gpx> becomes the default namespace in the XPath expression. I am not sure if this is correct, and I have not looked this up in the specification.
Maybe someone who is more knowledgeable can tell if this behaviour is correct. For now, I suggest you use the additional $title variable.
I think what you see is an XQuery 4 change, it should be possible to add a declaration in the query prolog
declare fixed default element namespace "";
to ensure the XPaths inside direct element constructors are not influenced by xmlns declarations on those element constructors but at least in the BaseX fiddle that currently gives an error.
Hi Jörn,
The behavior is compliant with the spec: The default namespace of node tests in path expressions is affected by default namespace declarations (xmlns="") appearing on element constructors.
You can achieve the expected result by using wildcards or the "Q{uri}local" syntax in the path…
$w/*:title/text() $w/Q{}title/text()
…or by moving the path outside the element constructor.
With XQuery 4 (as indicated by Martin), it will be possible to change the default behavior by introducing the query with a declaration that changes the default behavior:
declare fixed default element namespace '';
This syntax will be supported in one of the next versions of BaseX.
Best, Christian
Jörn Willhöft jwi@willhoeft-it.com schrieb am Do., 9. Jan. 2025, 19:23:
Hi all,
I just come across an issue, and I am not sure if I am too stupid to see the mistake, or it is a bug in BaseX.
I need to create an XML document from data in BaseX 11.5 inside basexgui. The data in the database does not use any namespaces. The document I am creating must have a default namespace set. Here is a stripped down example of my XQuery:
for $w in /json/workouts/_/header[uuid='123'] return
<gpx xmlns="http://www.topografix.com/GPX/1/1" > <title>{$w/title/text()}</title> </gpx>
Strangely all XPaths inside and outside the gpx-element will not match anything as long as I have the default namespace on the gpx-element defined. It works if I drop the xmlns attribute or I define the namespace explicitly, like:
for $w in /json/workouts/_/header[uuid='123'] return <g:gpx xmlns:g="http://www.topografix.com/GPX/1/1" > <g:title>{$w/title/text()}</g:title> </g:gpx>
Even though this should be semantically equal to the output of the above, the third party app that I import this to does not recognize it as such.
This is puzzling me mainly because I do not see, why the namespace I define for the *output* xml should have an impact on the queries that are directed to my database. As a workaround I will probably use a regex to remove the namespace, but that's obviously pretty awkward.
Any ideas?
Cheers Jörn
Hi Christian,
thanks for your explanation. So it's not a bug, but a somewhat counter-intuitive ehm.. "spec feature" :-) I can also confirm that XPaths outside the element are not affected by the default namespace. I think I wrote the opposite previously. So the example
for $w in /json/workouts/_/header[uuid='123'] let $outside := $w/title/text() return <gpx xmlns="http://www.topografix.com/GPX/1/1" > <title>{$w/title/text()}</title> <fromOutside>{$outside}</fromOutside> </gpx>
Would yield something like:
<gpx xmlns="http://www.topografix.com/GPX/1/1"> <title/> <fromOutside>Blablabla</fromOutside> </gpx>
And also good to hear that the case is already addressed in the future BaseX release!
Cheers
Jörn
Christian Grün christian.gruen@gmail.com hat am 11.01.2025 13:45 CET geschrieben:
Hi Jörn,
The behavior is compliant with the spec: The default namespace of node tests in path expressions is affected by default namespace declarations (xmlns="") appearing on element constructors.
You can achieve the expected result by using wildcards or the "Q{uri}local" syntax in the path…
$w/*:title/text() $w/Q{}title/text()
…or by moving the path outside the element constructor.
With XQuery 4 (as indicated by Martin), it will be possible to change the default behavior by introducing the query with a declaration that changes the default behavior:
declare fixed default element namespace '';
This syntax will be supported in one of the next versions of BaseX.
Best, Christian
Jörn Willhöft <jwi@willhoeft-it.com mailto:jwi@willhoeft-it.com> schrieb am Do., 9. Jan. 2025, 19:23:
Hi all,
I just come across an issue, and I am not sure if I am too stupid to see the mistake, or it is a bug in BaseX.
I need to create an XML document from data in BaseX 11.5 inside basexgui. The data in the database does not use any namespaces. The document I am creating must have a default namespace set. Here is a stripped down example of my XQuery:
for $w in /json/workouts/_/header[uuid='123'] return
<gpx xmlns="http://www.topografix.com/GPX/1/1" > <title>{$w/title/text()}</title> </gpx>
Strangely all XPaths inside and outside the gpx-element will not match anything as long as I have the default namespace on the gpx-element defined. It works if I drop the xmlns attribute or I define the namespace explicitly, like:
for $w in /json/workouts/_/header[uuid='123'] return <g:gpx xmlns:g="http://www.topografix.com/GPX/1/1" > <g:title>{$w/title/text()}</g:title> </g:gpx>
Even though this should be semantically equal to the output of the above, the third party app that I import this to does not recognize it as such.
This is puzzling me mainly because I do not see, why the namespace I define for the *output* xml should have an impact on the queries that are directed to my database. As a workaround I will probably use a regex to remove the namespace, but that's obviously pretty awkward.
Any ideas?
Cheers Jörn
basex-talk@mailman.uni-konstanz.de