Re: When and how are xs:anyURI references made absolute?

Hi again,

Just to clarify a bit how I got into this issue and my assumptions.

I wanted to create a custom XProc step that should receive a reference 
to a file as an option and I placed the definition of that step into a 
library file.
Now, the built-in steps, such as p:load, when receiving an option 
pointing to a file, in this case href, will resolve that relative to the 
place the option was specified, where the p:load step is called from.

My assumption was that Calabash does that for the built in steps, taking 
the base URI for options the place where the option value was specified 
in the calling code, but it does not do that for user defines steps.

 From my point of view, I just want to be able to declare a step 
somewhere in a library file (where the library location is completely 
arbitrary because it may be resolved via a catalog) and be able to 
resolve file reference options relative to the calling code, not to the 
library location, in the same way this is done for built in steps.

Reading the spec, the relevant fragments that I found appeared to 
confirm my assumption that Calabash should resolve the references using 
the base URI of the calling code.

However, this was not actually the case, it turns out that the step 
implementation computes the absolute URI, but for doing that, it has 
access to the base URI where the option is specified in the calling step.
That base URI of the place where the option is specified in the calling 
code seems to be really relevant information for an option, and if that 
will be made accessible not only to built-in/extension steps, but also 
to steps defined in XProc, then it will solve my initial problem, 
because I can use that in the defined step to resolve the relative URI 
in the same way the built-in steps do.

So, I guess exposing:

opt.context.baseUri

***
https://codeberg.org/xmlcalabash/xmlcalabash3/src/commit/f5c5e77121fb7df8c85c8260dc10e91e32279ca6/xmlcalabash/src/main/kotlin/com/xmlcalabash/steps/AbstractAtomicStep.kt#L231
***

to be accessible also to custom steps defined in XProc will be really 
useful.

I can then probably use something like:

p:urify($href, p:option-context-baseUri('href'))

to compute the absolute location similar to built-in steps.

Best Regards,
George
--
George Cristian Bina
<oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
http://www.oxygenxml.com

On 6/27/25 17:02, George Bina wrote:
> Hi again,
> 
> I just realized that argument here is wrong, sorry:
>  > Imagine this was a built-in step, it makes sense to have such a step
>  > probably as a built-in step, what type you would have used for its
>  > options? Not xs:anyURI for sure, because it will not work for exactly
>  > the reasons you mentioned, the local URI reference is resolved for
>  > built-in steps.
> 
> Thinking more about this... a difference between a built-in step and a 
> user defined step is that the custom step does not have access to the 
> base URI of the option in the caller step. If that will be available, 
> via some function for example, then the user defined step may use it to 
> resolve a relative URI and provide a behavior similar to the built-in 
> steps.
> 
> Best Regards,
> George
> -- 
> George Cristian Bina
> <oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
> http://www.oxygenxml.com
> 
> On 6/27/25 15:38, George Bina wrote:
>> Hi,
>>
>> FWIW, the example with the namespace-rename step I think has a few 
>> aspects that were not taken into account, see below:
>>
>> Imagine this was a built-in step, it makes sense to have such a step 
>> probably as a built-in step, what type you would have used for its 
>> options? Not xs:anyURI for sure, because it will not work for exactly 
>> the reasons you mentioned, the local URI reference is resolved for 
>> built-in steps.
>>
>> In my reading of the namespaces spec, the empty string in a namespace 
>> declaration is an empty string and not an empty relative URI, and it 
>> means no namespace:
>>
>> https://www.w3.org/TR/xml-names/#ns-decl
>> ***
>> The attribute's normalized value MUST be either a URI reference — the 
>> namespace name identifying the namespace — or an empty *string*.
>> ***
>>
>> This leads me to the conclusion that the implied type for managing 
>> both no namespace and specific namesapces is a reunion of URI 
>> references and (empty) string, therefore the appropriate type to use 
>> for a namespace rename step options is probably string and not anyURI.
>>
>> XML Schema uses '##local' to mean no namespace in some contexts, for 
>> example:
>> https://www.w3.org/TR/xmlschema-1/#element-anyAttribute
>> ***
>> namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace 
>> | ##local)) )  : ##any
>> ***
>>
>> Also xs:schema/@targetNamesapce does not use an empty value to mean no 
>> namespace, it models that with an absent attribute:
>> https://www.w3.org/TR/xmlschema-1/#ag-target_namespace
>> ***
>> {target namespace}
>>      Either ·absent· or a namespace name, as defined in [XML-Namespaces].
>> ***
>> and
>> https://www.w3.org/TR/xml-names/#iri-use
>> ***
>> The empty string, though it is a legal URI reference, cannot be used 
>> as a namespace name.
>> ***
>>
>>
>> Best Regards,
>> George
>> -- 
>> George Cristian Bina
>> <oXygen/> XML Editor, Schema Editor and XSLT Editor/Debugger
>> http://www.oxygenxml.com
>>
>> On 6/27/25 10:46, Norm Tovey-Walsh wrote:
>>> Earlier, I said that the proposed change in behavior had no effect on 
>>> my test suite results. That’s because I implemented it incorrectly. 
>>> On further attempts to implement it, about 30 tests fail. And some 
>>> steps are effectively no longer usable.
>>>
>>> Consider:
>>>
>>>    <p:namespace-rename to="http://example.com/ns"/>
>>>
>>> That step changes the namespace name of elements in no namespace so 
>>> that they’re in the http://example.com/ns namespace. It’s the same as:
>>>
>>>    <p:namespace-rename from="" to="http://example.com/ns"/>
>>>
>>> And “from” is declared as xs:anyURI. So with the proposed change, it 
>>> becomes, if not impossible, certainly wildly impractical, to pass the 
>>> empty string as an xs:anyURI value.
>>>
>>> I also tried to investigate the actual meaning of the xs:anyURI type. 
>>> The XML Schema definition of xs:anyURI has no facet for storing the 
>>> base URI, but explicitly says that the “value can be absolute or 
>>> relative, and may have an optional fragment identifier”. At the data 
>>> type level, a relative URI is free floating with no notion of its 
>>> “inherent” base URI.
>>>
>>> And, just to be sure, I tested the behavior of XSLT (I mean, I *knew* 
>>> what the behavior was, but I wrote the test anyway because that’s 
>>> safer.)
>>>
>>> If the behavior change proposed is extended beyond options to any 
>>> occurrence of an xs:anyURI (including, for example, in a p:variable), 
>>> then we’ll have behavior that is markedly different than XSLT:
>>>
>>> <?xml version="1.0" encoding="utf-8"?>
>>> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>>>                  xmlns:xs="http://www.w3.org/2001/XMLSchema"
>>>                  exclude-result-prefixes="xs"
>>>                  version="3.0">
>>>
>>> <xsl:output method="xml" encoding="utf-8" indent="no"/>
>>>
>>> <xsl:variable name="file"
>>>                xml:base="http://example.com/path/"
>>>                select="xs:anyURI('file.xml')"/>
>>>
>>> <xsl:template name="xsl:initial-template">
>>>    <xsl:call-template name="mytemplate">
>>>      <xsl:with-param name="file" select="$file"/>
>>>    </xsl:call-template>
>>> </xsl:template>
>>>
>>> <xsl:template name="mytemplate">
>>>    <xsl:param name="file" as="xs:anyURI"/>
>>>    <doc>
>>>      <file><xsl:sequence select="$file"/></file>
>>>      <abs><xsl:sequence select="resolve-uri($file)"/></abs>
>>>    </doc>
>>> </xsl:template>
>>>
>>> </xsl:stylesheet>
>>>
>>> That stylesheet produces <file>file.xml</file> and
>>> <abs>file:/tmp/file.xml</abs> (because the stylesheet was in /tmp so 
>>> that’s the static-base-uri() of the stylesheet.)
>>>
>>> Having the same behavior as XSLT is in no way a technical 
>>> requirement, but it is reasonable to argue that it’s “what users will 
>>> expect.”
>>>
>>> I’m coming around to the uncomfortable position that George is right 
>>> about what the spec says, but it doesn’t say what we meant. 
>>> Certainly, the p:namespace-rename case is strong evidence that 
>>> resolving a relative URI against a base URI was intended to be 
>>> selective, not universal.
>>>
>>>                                          Be seeing you,
>>>                                            norm
>>>
>>> -- 
>>> Norm Tovey-Walsh <ndw@nwalsh.com>
>>> https://norm.tovey-walsh.com/
>>>
>>>> The lasting pleasures of contact with the natural world are not 
>>>> reserved for scientists but are available to anyone who will place 
>>>> himself under the influence of the earth, sea and sky and their 
>>>> amazing life.--Rachel Carson
>>>
>>
> 

Received on Wednesday, 9 July 2025 08:24:10 UTC